00001 #ifndef EDG_WORKLOAD_COMMON_UTILITIES_FILECONTAINER_H
00002 #define EDG_WORKLOAD_COMMON_UTILITIES_FILECONTAINER_H
00003
00004 #include <unistd.h>
00005
00006 #include <exception>
00007 #include <iostream>
00008 #include <fstream>
00009 #include <vector>
00010 #include <string>
00011
00012 #include "edg/workload/common/common_namespace.h"
00013
00014
00015
00016
00017
00018 #define FILELIST_HAS_DEBUG_CODE
00019
00020 COMMON_NAMESPACE_BEGIN {
00021
00022 namespace utilities {
00023
00024 class FileIterator {
00025 inline friend std::ostream &operator<<( std::ostream &os, const FileIterator &fi ) { return fi.write( os ); }
00026 inline friend std::istream &operator>>( std::istream &is, FileIterator &fi ) { return fi.read( is ); }
00027
00028 public:
00029 FileIterator( std::streamoff prev = 0, std::streamoff next = 0, std::streamoff current = 0 );
00030
00031 ~FileIterator( void );
00032
00033 std::ostream &write( std::ostream &os ) const;
00034 std::istream &read( std::istream &is );
00035
00036 inline std::streamoff position( void ) const { return this->fi_current; }
00037 inline std::streamoff get_prev( void ) const { return this->fi_prev; }
00038 inline std::streamoff get_next( void ) const { return this->fi_next; }
00039 inline FileIterator &set_prev( std::streamoff prev ) { this->fi_prev = prev; return *this; }
00040 inline FileIterator &set_next( std::streamoff next ) { this->fi_next = next; return *this; }
00041 inline FileIterator &set_current( std::streamoff current ) { this->fi_current = current; return *this; }
00042 inline FileIterator &reset( std::streamoff prev = 0, std::streamoff next = 0, std::streamoff current = 0 )
00043 { this->fi_prev = prev; this->fi_next = next; this->fi_current = current; return *this; }
00044
00045 inline operator bool( void ) const { return this->fi_good; }
00046 inline bool operator!( void ) const { return !this->fi_good; }
00047
00048 inline static int size( void ) { return fi_s_width; }
00049
00050 private:
00051 void initialize( void );
00052
00053 bool fi_good;
00054 std::streamoff fi_prev, fi_next, fi_current;
00055
00056 static int fi_s_width;
00057 static FileIterator fi_s_iterator;
00058 };
00059
00060 class FileContainerError : public std::exception {
00061 public:
00062 enum iostatus_t { unknown = -1,
00063 all_good,
00064 cannot_open,
00065 file_closed,
00066 syntax_error,
00067 io_error,
00068 data_error,
00069 unavailable_position,
00070 container_modified,
00071 try_recover,
00072 unrecoverable_data,
00073 decrementing_from_zero,
00074 not_removing_last,
00075 _last_error
00076 };
00077
00078 FileContainerError( iostatus_t code = all_good );
00079 FileContainerError( iostatus_t code, const std::string &func, const char *file = NULL, int line = -1 );
00080
00081 ~FileContainerError( void ) throw();
00082
00083 std::string string_error( void ) const;
00084 virtual const char *what( void ) const throw();
00085
00086 inline iostatus_t code( void ) { return this->fce_code; }
00087 inline FileContainerError &set_code( iostatus_t code ) { this->fce_code = code; return *this; }
00088
00089 static const char *code_to_string( iostatus_t status );
00090
00091 private:
00092 int fce_line;
00093 iostatus_t fce_code;
00094 std::string fce_func, fce_file;
00095 mutable std::string fce_what;
00096
00097 static const char *fce_s_errors[];
00098 };
00099
00100 class FileContainer {
00101 public:
00102 enum filestatus_t { empty = ' ',
00103 opened = '1',
00104 closed = '0',
00105 ae_iterator = 'a',
00106 ae_limits,
00107 ae_writing,
00108 ae_written,
00109 ab_iterator,
00110 ab_writing,
00111 ab_written,
00112 ab_last,
00113 ab_limits,
00114 am_iterator1,
00115 am_iterator2,
00116 am_writing,
00117 am_written,
00118 am_last,
00119 rd_limits,
00120 rd_iterator,
00121 rd_iterator2,
00122 rd_iterator3,
00123 rd_mark1,
00124 rd_mark2,
00125 ft_begin,
00126 ft_end,
00127 ad_empty,
00128 rd_empty
00129 };
00130
00131 typedef FileContainerError::iostatus_t iostatus_t;
00132
00133 FileContainer( void );
00134 FileContainer( const char *filename );
00135
00136 ~FileContainer( void );
00137
00138 iostatus_t open( const char *filename );
00139 FileContainer &close( void );
00140
00141 iostatus_t add_data( const std::string &data, std::streamoff where, FileIterator &it );
00142 iostatus_t read_data( std::string &data, std::streamoff where, FileIterator &it, bool fileorder = false );
00143 iostatus_t remove_data( std::streamoff where );
00144 iostatus_t recover_data( filestatus_t status = closed, bool check = true );
00145 iostatus_t increment_iterator( FileIterator &it );
00146 iostatus_t decrement_iterator( FileIterator &it );
00147 iostatus_t increment_fileorder_iterator( FileIterator &it );
00148 iostatus_t decrement_fileorder_iterator( FileIterator &it );
00149 iostatus_t truncate( void );
00150 iostatus_t read_size( size_t &size );
00151 iostatus_t compact_data( void );
00152 iostatus_t sync( void );
00153 iostatus_t get_iterator( std::streamoff where, FileIterator &it );
00154 iostatus_t get_fileorder_iterator( std::streamoff where, FileIterator &it );
00155 iostatus_t modified( bool &mod );
00156 iostatus_t read_begin( std::streamoff &begin );
00157 iostatus_t read_end( std::streamoff &end );
00158 iostatus_t read_last( std::streamoff &last );
00159 iostatus_t read_file_end( std::streamoff &fileend );
00160 #ifdef FILELIST_HAS_DEBUG_CODE
00161 iostatus_t dump_status( const char *filename, iostatus_t status, const std::string &caller, int line );
00162 #endif
00163
00164 inline iostatus_t read_data( std::string &data, FileIterator &it ) { return this->read_data( data, it.position(), it ); }
00165 inline iostatus_t read_fileorder_data( std::string &data, FileIterator &it )
00166 { return this->read_data( data, it.position(), it, true ); }
00167 inline iostatus_t add_data( const std::string &data, FileIterator &it ) { return this->add_data( data, it.position(), it ); }
00168 inline iostatus_t remove_data( const FileIterator &it ) { return this->remove_data( it.position() ); }
00169 inline iostatus_t initialize( void ) { return this->initContainer(); }
00170 inline iostatus_t force_backup( const char *backupfile = NULL ) { return this->backupFile( backupfile ); }
00171 inline std::streamoff file_begin( void ) { return fc_s_headerSize; }
00172 inline std::streamoff start( void ) { return 0; }
00173 inline std::fstream &get_stream( void ) { return *this->fc_stream; }
00174
00175 inline const std::string &filename( void ) const { return this->fc_filename; }
00176
00177 private:
00178 const FileContainer &operator=( const FileContainer & );
00179 FileContainer( const FileContainer & );
00180
00181 class TimeStamp;
00182
00183 iostatus_t openFile( void );
00184 iostatus_t createFile( void );
00185 iostatus_t syncData( bool stamp = true );
00186 iostatus_t createEmptyFile( void );
00187 iostatus_t eraseFile( off_t size = 0 );
00188 iostatus_t truncateFile( off_t size );
00189 iostatus_t readStamp( void );
00190 iostatus_t writeStamp( void );
00191 iostatus_t writeFileStatus( filestatus_t fs );
00192 iostatus_t readFileStatus( filestatus_t &fs );
00193 iostatus_t readSize( void );
00194 iostatus_t writeAndSetSize( size_t num );
00195 iostatus_t createEmptyBackup( filestatus_t status );
00196 iostatus_t writeIteratorBackup( int what, const FileIterator &it, filestatus_t status );
00197 iostatus_t readIteratorBackup( int what, FileIterator &it );
00198 iostatus_t writeLimitsBackup( filestatus_t status, const FileIterator &it, bool isList = false );
00199 iostatus_t readLimitsBackup( FileIterator &it, bool isList = false );
00200 iostatus_t writeInitialPosition( const FileIterator &limits, bool isList = false );
00201 iostatus_t readInitialPosition( FileIterator &limits, bool isList = false );
00202 iostatus_t updateTimeStamp( void );
00203 iostatus_t checkStream( bool recover = true );
00204 iostatus_t checkStreamAndStamp( bool recover = true );
00205 iostatus_t checkStamp( bool &modified );
00206 iostatus_t readIteratorHere( FileIterator &it );
00207 iostatus_t readIterator( std::streamoff where, FileIterator &it, bool fileorder = false );
00208 iostatus_t writeIterator( std::streamoff where, const FileIterator &it );
00209 iostatus_t resetNextOfLast( filestatus_t status );
00210 iostatus_t writeDataHeader( const FileIterator &it, std::string::size_type size, char state );
00211 iostatus_t writeDataHere( const FileIterator &it, const FileIterator &lit, const std::string &data, filestatus_t status );
00212 iostatus_t addDataAtBegin( const std::string &data, FileIterator &it, std::streamoff end );
00213 iostatus_t addDataAtEnd( const std::string &data, FileIterator &it, std::streamoff end );
00214 iostatus_t addDataInMiddle( const std::string &data, FileIterator &it, std::streamoff where, std::streamoff end );
00215 iostatus_t readDataHere( FileIterator &it, FileIterator &itList, std::string &data, bool force = false );
00216 iostatus_t readSizeAndState( std::string::size_type &size, char &state );
00217 iostatus_t removeDataPointer( const FileIterator &it, std::string::size_type size );
00218 iostatus_t markDataAsErased( const FileIterator &it, std::string::size_type size, filestatus_t status );
00219 iostatus_t markDataAsUnerased( const FileIterator &it );
00220 iostatus_t backupFile( const char *backupfile = NULL );
00221 iostatus_t fillVector( std::vector<std::string> &vec );
00222 iostatus_t initContainer( void );
00223 iostatus_t checkConsistency( int allowable_size_offset );
00224
00225 inline std::streamoff getEnd( void ) { this->fc_stream->seekp( 0, std::ios::end ); return this->fc_stream->tellp(); }
00226 inline std::streamoff getBegin( void ) { return this->fc_limits.get_prev(); }
00227
00228 static void staticInitialize( void );
00229
00230 bool fc_initialized;
00231 size_t fc_size;
00232 std::fstream *fc_stream;
00233 TimeStamp *fc_stamp;
00234 std::string fc_filename;
00235 FileIterator fc_limits, fc_removed;
00236 #ifdef FILELIST_HAS_DEBUG_CODE
00237 std::vector<std::string> fc_callStack;
00238
00239 class StackPusher {
00240 public:
00241 StackPusher( std::vector<std::string> &callstack, const char *format, ... );
00242 ~StackPusher( void );
00243
00244 private:
00245 std::vector<std::string> &sp_callstack;
00246 };
00247 #endif
00248
00249 static int fc_s_stampSize, fc_s_sizeSize, fc_s_headerSize, fc_s_backupSize;
00250 static int fc_s_iteratorBackupSize, fc_s_limitsBackupSize, fc_s_numberSize;
00251 static int fc_s_statusPosition, fc_s_positionPosition;
00252 static int fc_s_listBackupSize, fc_s_listPosition;
00253 static const int fc_s_iteratorBackupNumber;
00254 };
00255
00256 #ifdef FILELIST_HAS_DEBUG_CODE
00257 void throwErrorAndDumpFile( FileContainer &cont, FileContainerError::iostatus_t status,
00258 const std::string &func, const std::string &filename, int line, bool doThrow = true );
00259 #else
00260 #define throwErrorAndDumpFile( container, status, func, filename, line ) \
00261 throw FileContainerError( (status), (func), (filename).c_str(), (line) )
00262 #endif
00263
00264 };
00265
00266 } COMMON_NAMESPACE_END;
00267
00268 #endif
00269
00270
00271
00272