NCBI C++ ToolKit
chunk_file.cpp
Go to the documentation of this file.

Go to the SVN repository for this file.

1 /* $Id: chunk_file.cpp 91383 2020-10-21 16:07:12Z grichenk $
2  * ===========================================================================
3  *
4  * PUBLIC DOMAIN NOTICE
5  * National Center for Biotechnology Information
6  *
7  * This software/database is a "United States Government Work" under the
8  * terms of the United States Copyright Act. It was written as part of
9  * the author's official duties as a United States Government employee and
10  * thus cannot be copyrighted. This software/database is freely available
11  * to the public for use. The National Library of Medicine and the U.S.
12  * Government have not placed any restriction on its use or reproduction.
13  *
14  * Although all reasonable efforts have been taken to ensure the accuracy
15  * and reliability of the software and data, the NLM and the U.S.
16  * Government do not and cannot warrant the performance or results that
17  * may be obtained by using this software or data. The NLM and the U.S.
18  * Government disclaim all warranties, express or implied, including
19  * warranties of performance, merchantability or fitness for any particular
20  * purpose.
21  *
22  * Please cite the author in any work or product based on this material.
23  *
24  * ===========================================================================
25  *
26  * Authors: Cheinan Marks
27  *
28  * File Description: See chunk_file.hpp
29  */
30 
31 #include <ncbi_pch.hpp>
32 
33 #include <string>
34 #include <fstream>
35 #include <sstream>
36 #include <iomanip>
37 
38 #include <corelib/ncbifile.hpp>
39 #include <corelib/ncbistre.hpp>
40 
41 #include <serial/serial.hpp>
42 #include <serial/objostrasnb.hpp>
43 #include <serial/objistrasnb.hpp>
44 
49 
51 using objects::CCache_blob;
52 
53 
54 void CChunkFile::OpenForWrite( const string & root_path )
55 {
56  if (!root_path.empty() && m_OpenFileRootPath != root_path) {
57  m_OpenFileRootPath = root_path;
58  m_ChunkSerialNum = 1;
59  m_ChunkSize = -1;
60  }
61  if (m_ChunkSize < 0) {
62  Uint8 new_chunk_size;
64  m_ChunkSize = new_chunk_size;
65  } else if (m_ChunkSize > m_kMaxChunkSize) {
67  m_ChunkSize = 0;
68  }
70 
71  if ( file_path != GetPath() ) {
72  Reset( file_path );
73 
74  m_FileStream.close();
75  m_FileStream.clear();
76  if( Exists() ) {
77  m_FileStream.open( file_path.c_str(),
78  ios::out | ios::binary | ios::app );
79  } else {
80  m_FileStream.open( file_path.c_str(), ios::out | ios::binary );
81  LOG_POST( Info << "Chunk file " << file_path
82  << " does not exist. Creating." );
83  }
84  }
85 
86  if ( ! m_FileStream ) {
87  int saved_errno = NCBI_ERRNO_CODE_WRAPPER();
88  string error_string =
89  "Unable to open a chunk file for writing at " + file_path ;
90  error_string += " (errno = " + NStr::NumericToString( saved_errno ) + ": ";
91  error_string += string( NCBI_ERRNO_STR_WRAPPER( saved_errno ) +
92  string( ")" ) );
93  ERR_POST( Error << error_string );
94  NCBI_THROW( CASNCacheException, eCantOpenChunkFile, error_string );
95  }
96 }
97 
98 
99 void CChunkFile::OpenForRead( const string & root_path,
100  unsigned int chunk )
101 {
102  if (!root_path.empty() && m_OpenFileRootPath != root_path) {
103  m_OpenFileRootPath = root_path;
104  m_ChunkSerialNum = 1;
105  m_ChunkSize = -1;
106  }
107  if (chunk) {
108  m_ChunkSerialNum = chunk;
109  }
111  if ( file_path != GetPath() ) {
112  Reset( file_path );
113 
114  if( Exists() ) {
115  m_FileStream.close();
116  m_FileStream.clear();
117 
118  m_FileStream.open( file_path.c_str(), ios::in | ios::binary );
119  if ( ! m_FileStream ) {
120  int saved_errno = NCBI_ERRNO_CODE_WRAPPER();
121  string error_string =
122  "Unable to open a chunk file for reading at " + file_path ;
123  error_string += " (errno = " +
124  NStr::NumericToString( saved_errno ) + ": ";
125  error_string += string( NCBI_ERRNO_STR_WRAPPER( saved_errno ) +
126  string( ")" ) );
127  ERR_POST( Error << error_string );
128  NCBI_THROW( CASNCacheException, eCantOpenChunkFile,
129  error_string );
130  }
131  } else {
132  string error_string = "Tried to read nonexistant chunk file at "
133  + file_path;
134  ERR_POST( Error << error_string );
135  NCBI_THROW( CASNCacheException, eCantOpenChunkFile, error_string );
136  }
137  }
138 }
139 
140 
141 void CChunkFile::Write( const CCache_blob & cache_blob )
142 {
144  asn_stream << cache_blob;
145  asn_stream.Flush();
146  m_ChunkSize += asn_stream.GetStreamPos();
147 }
148 
149 
150 void CChunkFile::RawWrite( const char * raw_data, size_t raw_data_size )
151 {
152  m_FileStream.write( raw_data, raw_data_size );
153  m_ChunkSize += raw_data_size;
154 }
155 
156 
157 void CChunkFile::Read( CCache_blob & target_blob, streampos offset,
158  size_t blob_size )
159 {
160  m_Buffer.clear();
161  m_Buffer.resize( blob_size );
162 
163  m_FileStream.seekg( offset );
164  m_FileStream.read( &m_Buffer[0], blob_size );
165 
166  CObjectIStreamAsnBinary asn_stream( &m_Buffer[0], blob_size );
167  asn_stream >> target_blob;
168 }
169 
170 
171 void CChunkFile::RawRead( streampos offset, char * raw_data, size_t raw_data_size )
172 {
173  if (raw_data_size > static_cast< size_t >(std::numeric_limits< streamsize >::max())) {
175  "CChunkFile::RawRead(): " +
176  GetPath() +
177  ": requested a larger than supported number of bytes: " +
178  NStr::NumericToString(raw_data_size));
179  }
180  streamsize size(raw_data_size);
181  m_FileStream.seekg( offset );
182  m_FileStream.read( raw_data, size );
183  if ( m_FileStream.gcount() != size ) {
185  "CChunkFile::RawRead(): " +
186  GetPath() +
187  ": failed to read specified number of bytes: got " +
188  NStr::Int8ToString(m_FileStream.gcount()) + ", expected " +
189  NStr::UInt8ToString(raw_data_size) +
190  " (offset=" + NStr::UInt8ToString(offset) + ")");
191  }
192 }
193 
194 
195 size_t CChunkFile::Append( const string & root_path, const CFile & input_chunk_file,
196  Uint8 input_offset )
197 {
198  if (m_OpenFileRootPath != root_path) {
199  m_OpenFileRootPath = root_path;
200  m_ChunkSerialNum = 1;
201  m_ChunkSize = -1;
202  }
203  if (m_ChunkSize < 0) {
204  Uint8 new_chunk_size;
206  m_ChunkSize = new_chunk_size;
207  } else if (m_ChunkSize > m_kMaxChunkSize) {
209  m_ChunkSize = 0;
210  }
212  Reset( file_path );
213 
214  m_FileStream.open( file_path.c_str(), ios::app | ios::out | ios::binary );
215  CNcbiIfstream input_chunk_stream( input_chunk_file.GetPath().c_str(), ios::in | ios::binary );
216  input_chunk_stream.seekg( input_offset );
217  if (! NcbiStreamCopy( m_FileStream, input_chunk_stream ) ) {
218  ERR_POST( Error << "Append of " << input_chunk_file.GetPath() << " to " << file_path
219  << " at offset " << input_offset << " failed." );
220  return 0;
221  }
222 
223  m_ChunkSize += input_chunk_file.GetLength() - input_offset;
224 
225  return m_ChunkSerialNum;
226 }
227 
228 
229 string CChunkFile::s_MakeChunkFileName( const string & root_path, unsigned int serial_number )
230 {
231  ostringstream serial_number_stream;
232  serial_number_stream << setw( 5 ) << setfill( '0' ) << serial_number;
233  return CDirEntry::ConcatPath( root_path,
234  NASNCacheFileName::GetChunkPrefix() + serial_number_stream.str() );
235 }
236 
237 
238 unsigned int CChunkFile::s_FindNextChunk( const string & root_path,
239  unsigned int serial_num,
240  Uint8 &size )
241 {
242  while( true ) {
243  CFile chunk_file( s_MakeChunkFileName( root_path, serial_num ) );
244  if ( ! chunk_file.Exists() )
245  {
246  size = 0;
247  break;
248  } else if ( (size = chunk_file.GetLength()) < m_kMaxChunkSize )
249  {
250  break;
251  }
252  ++serial_num;
253  }
254 
255  return serial_num;
256 }
257 
258 
259 unsigned int CChunkFile::s_FindLastChunk( const string & root_path )
260 {
261  unsigned int serial_num = 1;
262  while( true ) {
263  CFile chunk_file( s_MakeChunkFileName( root_path, serial_num ) );
264  if ( ! chunk_file.Exists() ) {
265  break;
266  }
267  ++serial_num;
268  }
269 
270  return serial_num - 1;
271 }
272 
273 
275 
User-defined methods of the data storage class.
Int8 m_ChunkSize
Definition: chunk_file.hpp:83
size_t Append(const string &root_path, const CFile &input_chunk_file, Uint8 input_offset=0)
Definition: chunk_file.cpp:195
void Read(CCache_blob &target, std::streampos offset, size_t blob_size)
Definition: chunk_file.cpp:157
static std::string s_MakeChunkFileName(const std::string &root_path, unsigned int serial_num)
Definition: chunk_file.cpp:229
unsigned int m_ChunkSerialNum
Definition: chunk_file.hpp:82
static unsigned int s_FindNextChunk(const std::string &root_path, unsigned int serial_num, Uint8 &size)
Definition: chunk_file.cpp:238
CNcbiFstream m_FileStream
Definition: chunk_file.hpp:84
void OpenForWrite(const std::string &root_path="")
Definition: chunk_file.cpp:54
void RawWrite(const char *raw_blob, size_t raw_blob_size)
Definition: chunk_file.cpp:150
CSimpleBufferT< char > m_Buffer
Definition: chunk_file.hpp:87
void Write(const CCache_blob &cache_blob)
Definition: chunk_file.cpp:141
void OpenForRead(const std::string &root_path="", unsigned int chunk=0)
Definition: chunk_file.cpp:99
static const Int8 m_kMaxChunkSize
Definition: chunk_file.hpp:91
void RawRead(std::streampos offset, char *raw_blob, size_t raw_blob_size)
Definition: chunk_file.cpp:171
static unsigned int s_FindLastChunk(const std::string &root_path)
Definition: chunk_file.cpp:259
std::string m_OpenFileRootPath
Definition: chunk_file.hpp:86
CFile –.
Definition: ncbifile.hpp:1604
CObjectIStreamAsnBinary –.
Definition: objistrasnb.hpp:59
CObjectOStreamAsnBinary –.
Definition: objostrasnb.hpp:58
void resize(size_type new_size)
std::ofstream out("events_result.xml")
main entry point for tests
int offset
Definition: replacements.h:160
string
Definition: cgiapp.hpp:687
#define ERR_POST(message)
Error posting with file, line number information but without error codes.
Definition: ncbidiag.hpp:186
#define LOG_POST(message)
This macro is deprecated and it's strongly recomended to move in all projects (except tests) to macro...
Definition: ncbidiag.hpp:226
void Error(CExceptionArgs_Base &args)
Definition: ncbiexpt.hpp:1197
#define NCBI_ERRNO_CODE_WRAPPER
Definition: ncbiexpt.hpp:1529
#define NCBI_THROW(exception_class, err_code, message)
Generic macro to throw an exception, given the exception class, error code and message string.
Definition: ncbiexpt.hpp:704
#define NCBI_ERRNO_STR_WRAPPER
Definition: ncbiexpt.hpp:1530
void Info(CExceptionArgs_Base &args)
Definition: ncbiexpt.hpp:1185
Int8 GetLength(void) const
Get size of file.
Definition: ncbifile.cpp:3204
static string ConcatPath(const string &first, const string &second)
Concatenate two parts of the path for the current OS.
Definition: ncbifile.cpp:776
void Reset(const string &path)
Reset path string.
Definition: ncbifile.cpp:298
const string & GetPath(void) const
Get entry path.
Definition: ncbifile.hpp:3910
virtual bool Exists(void) const
Check existence of file.
Definition: ncbifile.hpp:4038
@ eUnknown
Unknown type.
Definition: ncbifile.hpp:793
CNcbiStreampos GetStreamPos(void) const
Get the current stream position.
Definition: objostr.cpp:505
void Flush(void)
uint64_t Uint8
8-byte (64-bit) unsigned integer
Definition: ncbitype.h:105
#define END_NCBI_SCOPE
End previously defined NCBI scope.
Definition: ncbistl.hpp:103
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
Definition: ncbistl.hpp:100
IO_PREFIX::ifstream CNcbiIfstream
Portable alias for ifstream.
Definition: ncbistre.hpp:439
bool NcbiStreamCopy(CNcbiOstream &os, CNcbiIstream &is)
Copy the entire contents of stream "is" to stream "os".
Definition: ncbistre.cpp:211
static string Int8ToString(Int8 value, TNumToStringFlags flags=0, int base=10)
Convert Int8 to string.
Definition: ncbistr.hpp:5159
static enable_if< is_arithmetic< TNumeric >::value||is_convertible< TNumeric, Int8 >::value, string >::type NumericToString(TNumeric value, TNumToStringFlags flags=0, int base=10)
Convert numeric value to string.
Definition: ncbistr.hpp:673
static string UInt8ToString(Uint8 value, TNumToStringFlags flags=0, int base=10)
Convert UInt8 to string.
Definition: ncbistr.hpp:5168
string GetChunkPrefix()
Definition: file_names.hpp:53
const struct ncbi::grid::netcache::search::fields::SIZE size
Defines classes: CDirEntry, CFile, CDir, CSymLink, CMemoryFile, CFileUtil, CFileLock,...
NCBI C++ stream class wrappers for triggering between "new" and "old" C++ stream libraries.
T max(T x_, T y_)
std::istream & in(std::istream &in_, double &x_)
Modified on Tue Apr 23 07:39:59 2024 by modify_doxy.py rev. 669887