SSM
|
00001 #ifndef SSM_LOG_HPP__ 00002 #define SSM_LOG_HPP__ 00003 00004 #include <fstream> 00005 #include <string> 00006 #include <sstream> 00007 00008 #include <ssm.hpp> 00009 00010 class SSMLogBase 00011 { 00012 protected: 00013 std::fstream *mLogFile; 00014 ssmTimeT mTime; 00015 void *mData; 00016 size_t mDataSize; 00017 void *mProperty; 00018 size_t mPropertySize; 00019 std::string mStreamName; 00020 int mStreamId; 00021 int mBufferNum; // ssmのリングバッファの個数 00022 double mCycle; // streamへの書き込みサイクル 00023 ssmTimeT mStartTime; // logを書き込み始めた時間 00024 std::ios::pos_type mStartPos; // logの開始位置 00025 std::ios::pos_type mEndPos; // logの終了位置 00026 std::ios::pos_type mPropertyPos; // propertyの書き込み位置 00027 00028 void init() 00029 { 00030 mData = NULL; 00031 mDataSize = 0; 00032 mProperty = NULL; 00033 mPropertySize = 0; 00034 mStreamId = 0; 00035 mBufferNum = 0; 00036 mCycle = 0.0; 00037 mStartTime = 0.0; 00038 } 00039 00040 bool writeProperty() 00041 { 00042 mLogFile->seekp( mPropertyPos ); 00043 mLogFile->write( (char *)mProperty, mPropertySize ); 00044 return true; 00045 } 00046 00047 bool getLogInfo() 00048 { 00049 std::string line; 00050 mLogFile->seekg( 0, std::ios::beg ); 00051 if( !getline( *mLogFile, line ) ) 00052 return false; 00053 std::istringstream data( line.c_str( ) ); 00054 00055 data 00056 >> mStreamName 00057 >> mStreamId 00058 >> mDataSize 00059 >> mBufferNum 00060 >> mCycle 00061 >> mStartTime 00062 >> mPropertySize 00063 ; 00064 if( data.fail() ) 00065 return false; 00066 #if 0 00067 std::cout 00068 << mStreamName << ' ' 00069 << mStreamId << ' ' 00070 << mDataSize << ' ' 00071 << mBufferNum << ' ' 00072 << mCycle << ' ' 00073 << mStartTime << ' ' 00074 << mPropertySize 00075 << std::endl; 00076 #endif 00077 // プロパティの読み込み 00078 mPropertyPos = mLogFile->tellg(); 00079 if( mProperty ) 00080 readProperty(); 00081 else 00082 mLogFile->seekg( mPropertySize, std::ios::cur ); 00083 00084 // ログ位置の保存 00085 mStartPos = mLogFile->tellg(); 00086 mLogFile->seekg(0, std::ios::end ); 00087 mEndPos = mLogFile->tellg(); 00088 mLogFile->seekg( mStartPos ); 00089 00090 mTime = mStartTime; 00091 00092 return true; 00093 } 00094 00095 bool setLogInfo() 00096 { 00097 mLogFile->setf(std::ios::fixed); 00098 mLogFile->seekp( 0, std::ios::beg ); 00099 mStartTime = gettimeSSM(); 00100 *mLogFile 00101 << mStreamName << ' ' 00102 << mStreamId << ' ' 00103 << mDataSize << ' ' 00104 << mBufferNum << ' ' 00105 << mCycle << ' ' 00106 << mStartTime << ' ' 00107 << mPropertySize 00108 << std::endl; 00109 00110 // プロパティの書き込み 00111 mPropertyPos = mLogFile->tellp(); 00112 writeProperty(); 00113 00114 // ログ開始位置の保存 00115 mStartPos = mLogFile->tellp(); 00116 return true; 00117 } 00118 00119 public: 00120 SSMLogBase() 00121 { 00122 init(); 00123 } 00124 00125 virtual ~SSMLogBase() 00126 { 00127 } 00128 void setBuffer(void *data, size_t dataSize, void *property, size_t propertySize ) 00129 { 00130 mData = data; 00131 mDataSize = dataSize; 00132 mProperty = property; 00133 mPropertySize = propertySize; 00134 } 00135 00136 bool readProperty() 00137 { 00138 int curPos; 00139 curPos = mLogFile->tellg(); 00140 00141 mLogFile->seekg( mPropertyPos, std::ios::beg ); 00142 mLogFile->read( (char *)mProperty, mPropertySize ); 00143 00144 mLogFile->seekg( curPos, std::ios::beg ); 00145 return true; 00146 } 00147 00148 bool open( const char *fileName ) 00149 { 00150 mLogFile = new std::fstream( ); 00151 mLogFile->open( fileName, std::ios::in ); 00152 if( !mLogFile->is_open( ) ) 00153 { 00154 delete mLogFile; 00155 std::cerr << "SSMLogBase::open : cannot open log file '" << fileName << "'." << std::endl; 00156 return false; 00157 } 00158 if( !getLogInfo( ) ) 00159 { 00160 std::cerr << "SSMLogBase::open : '" << fileName << "' is NOT ssm-log file." << std::endl; 00161 return false; 00162 } 00163 return true; 00164 } 00165 00166 bool create( const char *streamName, int streamId, int bufferNum, double cycle, const char *fileName ) 00167 { 00168 mLogFile = new std::fstream( ); 00169 mLogFile->open( fileName, std::ios::out | std::ios::trunc ); 00170 mStreamName = streamName; 00171 mStreamId = streamId; 00172 mBufferNum = bufferNum; 00173 mCycle = cycle; 00174 if( !mLogFile->is_open( ) ) 00175 return false; 00176 if( !setLogInfo( ) ) 00177 return false; 00178 return true; 00179 } 00180 00181 bool close( ) 00182 { 00183 delete mLogFile; 00184 return true; 00185 } 00186 00187 virtual bool write( ssmTimeT time = gettimeSSM( ) ) 00188 { 00189 mTime = time; 00190 mLogFile->write( (char *)&mTime, sizeof( ssmTimeT ) ); 00191 mLogFile->write( (char *)mData, mDataSize ); 00192 return true; 00193 } 00194 00195 virtual bool read( ) 00196 { 00197 mLogFile->read( (char *)&mTime, sizeof( ssmTimeT ) ); 00198 mLogFile->read( (char *)mData, mDataSize ); 00199 return mLogFile->good( ); 00200 } 00201 00202 bool readNext( ) 00203 { 00204 return read( ); 00205 } 00206 00207 bool readBack( ) 00208 { 00209 return seek( -2 ) && read(); 00210 } 00211 00212 // read時専用 00213 bool seek( int diff ) 00214 { 00215 mLogFile->clear( ); // eofになっているとseekできないので 00216 std::fstream::pos_type pos,curPos = mLogFile->tellg(); 00217 // シーク 00218 mLogFile->seekg( static_cast<int>( sizeof( ssmTimeT ) + mDataSize ) * diff, std::ios::cur ); 00219 // シークに成功したかをチェック 00220 pos = mLogFile->tellg( ); 00221 if( pos < mStartPos || pos > mEndPos ) 00222 { 00223 // シーク失敗なら終了 00224 mLogFile->seekg( curPos ); 00225 return false; 00226 } 00227 return true; 00228 } 00229 00230 // @brief 時間指定読み込み 00231 // 指定した時間より前で最も近いデータを読み込む 00232 bool readTime( ssmTimeT time ) 00233 { 00234 std::ios::pos_type curPos = mLogFile->tellg(); 00235 // cycleを使って予測ジャンプ 00236 seek( ( time - mTime ) / mCycle ); 00237 // 現在位置を読み込み 00238 readNext() || readBack(); // 一番最後だと読み込めないので1つ戻って読み込む 00239 00240 // 条件を満たすまで探索 00241 mLogFile->clear( ); 00242 while( mTime < time && readNext( ) ); 00243 mLogFile->clear( ); 00244 while( mTime >= time && readBack( ) ); 00245 00246 return true; 00247 } 00248 00249 const ssmTimeT &getStartTime( ) const 00250 { 00251 return mStartTime; 00252 } 00253 00254 ssmTimeT &time( ) 00255 { 00256 return mTime; 00257 } 00258 void *data( ) 00259 { 00260 return mData; 00261 } 00262 size_t &dataSize( ) 00263 { 00264 return mDataSize; 00265 } 00266 00267 void *property( ) 00268 { 00269 return mProperty; 00270 } 00271 size_t &propertySize() 00272 { 00273 return mPropertySize; 00274 } 00275 00276 const char *getStreamName( ) const 00277 { 00278 return mStreamName.c_str(); 00279 } 00280 00281 const int &getStreamId( ) const { return mStreamId; } 00282 00283 const double &getCycle( ) const { return mCycle; } 00284 00285 const int &getBufferNum( ) const { return mBufferNum; } 00286 00287 }; 00288 00289 template < typename D, typename P = SSMDummy > class SSMLog : public SSMLogBase 00290 { 00291 void setBuffer(void *data, size_t dataSize, void *property, size_t propertySize ); 00292 void initLog() 00293 { 00294 SSMLogBase::setBuffer( &dataBuf, sizeof( D ), &propertyBuf, sizeof( P ) ); 00295 } 00296 D dataBuf; // @brief SSM Data. 00297 P propertyBuf; // @brief Property of SSM Data. 00298 public: 00299 00300 SSMLog( ) 00301 { 00302 initLog(); 00303 } 00304 00305 virtual ~SSMLog( ){} 00306 00307 D &data( ) 00308 { 00309 return dataBuf; 00310 } 00311 00312 P &property( ) 00313 { 00314 return propertyBuf; 00315 } 00316 }; 00317 #endif // SSM_LOG_H__