FileStore.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 ** Copyright (c) 2001-2014
3 **
4 ** This file is part of the QuickFIX FIX Engine
5 **
6 ** This file may be distributed under the terms of the quickfixengine.org
7 ** license as defined by quickfixengine.org and appearing in the file
8 ** LICENSE included in the packaging of this file.
9 **
10 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
11 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
12 **
13 ** See http://www.quickfixengine.org/LICENSE for licensing information.
14 **
15 ** Contact ask@quickfixengine.org if any conditions of this licensing are
16 ** not clear to you.
17 **
18 ****************************************************************************/
19 
20 #ifdef _MSC_VER
21 #include "stdafx.h"
22 #else
23 #include "config.h"
24 #endif
25 
26 #include "FileStore.h"
27 #include "SessionID.h"
28 #include "Parser.h"
29 #include "Utility.h"
30 #include <fstream>
31 
32 namespace FIX
33 {
34 FileStore::FileStore( std::string path, const SessionID& s )
35 : m_msgFile( 0 ), m_headerFile( 0 ), m_seqNumsFile( 0 ), m_sessionFile( 0 )
36 {
37  file_mkdir( path.c_str() );
38 
39  if ( path.empty() ) path = ".";
40  const std::string& begin =
41  s.getBeginString().getString();
42  const std::string& sender =
43  s.getSenderCompID().getString();
44  const std::string& target =
45  s.getTargetCompID().getString();
46  const std::string& qualifier =
48 
49  std::string sessionid = begin + "-" + sender + "-" + target;
50  if( qualifier.size() )
51  sessionid += "-" + qualifier;
52 
53  std::string prefix
54  = file_appendpath(path, sessionid + ".");
55 
56  m_msgFileName = prefix + "body";
57  m_headerFileName = prefix + "header";
58  m_seqNumsFileName = prefix + "seqnums";
59  m_sessionFileName = prefix + "session";
60 
61  try
62  {
63  open( false );
64  }
65  catch ( IOException & e )
66  {
67  throw ConfigError( e.what() );
68  }
69 }
70 
72 {
73  if( m_msgFile ) fclose( m_msgFile );
74  if( m_headerFile ) fclose( m_headerFile );
75  if( m_seqNumsFile ) fclose( m_seqNumsFile );
76  if( m_sessionFile ) fclose( m_sessionFile );
77 }
78 
79 void FileStore::open( bool deleteFile )
80 {
81  if ( m_msgFile ) fclose( m_msgFile );
82  if ( m_headerFile ) fclose( m_headerFile );
83  if ( m_seqNumsFile ) fclose( m_seqNumsFile );
84  if ( m_sessionFile ) fclose( m_sessionFile );
85 
86  m_msgFile = 0;
87  m_headerFile = 0;
88  m_seqNumsFile = 0;
89  m_sessionFile = 0;
90 
91  if ( deleteFile )
92  {
93  file_unlink( m_msgFileName.c_str() );
94  file_unlink( m_headerFileName.c_str() );
95  file_unlink( m_seqNumsFileName.c_str() );
96  file_unlink( m_sessionFileName.c_str() );
97  }
98 
99  populateCache();
100  m_msgFile = file_fopen( m_msgFileName.c_str(), "r+" );
101  if ( !m_msgFile ) m_msgFile = file_fopen( m_msgFileName.c_str(), "w+" );
102  if ( !m_msgFile ) throw ConfigError( "Could not open body file: " + m_msgFileName );
103 
104  m_headerFile = file_fopen( m_headerFileName.c_str(), "r+" );
105  if ( !m_headerFile ) m_headerFile = file_fopen( m_headerFileName.c_str(), "w+" );
106  if ( !m_headerFile ) throw ConfigError( "Could not open header file: " + m_headerFileName );
107 
108  m_seqNumsFile = file_fopen( m_seqNumsFileName.c_str(), "r+" );
109  if ( !m_seqNumsFile ) m_seqNumsFile = file_fopen( m_seqNumsFileName.c_str(), "w+" );
110  if ( !m_seqNumsFile ) throw ConfigError( "Could not open seqnums file: " + m_seqNumsFileName );
111 
112  bool setCreationTime = false;
113  m_sessionFile = file_fopen( m_sessionFileName.c_str(), "r" );
114  if ( !m_sessionFile ) setCreationTime = true;
115  else fclose( m_sessionFile );
116 
117  m_sessionFile = file_fopen( m_sessionFileName.c_str(), "r+" );
118  if ( !m_sessionFile ) m_sessionFile = file_fopen( m_sessionFileName.c_str(), "w+" );
119  if ( !m_sessionFile ) throw ConfigError( "Could not open session file" );
120  if ( setCreationTime ) setSession();
121 
124 }
125 
127 {
128  FILE* headerFile = file_fopen( m_headerFileName.c_str(), "r+" );
129  if ( headerFile )
130  {
131  int num, offset, size;
132  while ( FILE_FSCANF( headerFile, "%d,%d,%d ", &num, &offset, &size ) == 3 )
133  m_offsets[ num ] = std::make_pair( offset, size );
134  fclose( headerFile );
135  }
136 
137  FILE* seqNumsFile = file_fopen( m_seqNumsFileName.c_str(), "r+" );
138  if ( seqNumsFile )
139  {
140  int sender, target;
141  if ( FILE_FSCANF( seqNumsFile, "%d : %d", &sender, &target ) == 2 )
142  {
145  }
146  fclose( seqNumsFile );
147  }
148 
149  FILE* sessionFile = file_fopen( m_sessionFileName.c_str(), "r+" );
150  if ( sessionFile )
151  {
152  char time[ 22 ];
153 #ifdef HAVE_FSCANF_S
154  int result = FILE_FSCANF( sessionFile, "%s", time, 22 );
155 #else
156  int result = FILE_FSCANF( sessionFile, "%s", time );
157 #endif
158  if( result == 1 )
159  {
161  }
162  fclose( sessionFile );
163  }
164 }
165 
167 {
168  if ( m_path.size() ) return new FileStore( m_path, s );
169 
170  std::string path;
171  Dictionary settings = m_settings.get( s );
172  path = settings.getString( FILE_STORE_PATH );
173  return new FileStore( path, s );
174 }
175 
177 {
178  delete pStore;
179 }
180 
181 bool FileStore::set( int msgSeqNum, const std::string& msg )
182 throw ( IOException )
183 {
184  if ( fseek( m_msgFile, 0, SEEK_END ) )
185  throw IOException( "Cannot seek to end of " + m_msgFileName );
186  if ( fseek( m_headerFile, 0, SEEK_END ) )
187  throw IOException( "Cannot seek to end of " + m_headerFileName );
188 
189  int offset = ftell( m_msgFile );
190  if ( offset < 0 )
191  throw IOException( "Unable to get file pointer position from " + m_msgFileName );
192  int size = msg.size();
193 
194  if ( fprintf( m_headerFile, "%d,%d,%d ", msgSeqNum, offset, size ) < 0 )
195  throw IOException( "Unable to write to file " + m_headerFileName );
196  m_offsets[ msgSeqNum ] = std::make_pair( offset, size );
197  fwrite( msg.c_str(), sizeof( char ), msg.size(), m_msgFile );
198  if ( ferror( m_msgFile ) )
199  throw IOException( "Unable to write to file " + m_msgFileName );
200  if ( fflush( m_msgFile ) == EOF )
201  throw IOException( "Unable to flush file " + m_msgFileName );
202  if ( fflush( m_headerFile ) == EOF )
203  throw IOException( "Unable to flush file " + m_headerFileName );
204  return true;
205 }
206 
207 void FileStore::get( int begin, int end,
208  std::vector < std::string > & result ) const
209 throw ( IOException )
210 {
211  result.clear();
212  std::string msg;
213  for ( int i = begin; i <= end; ++i )
214  {
215  if ( get( i, msg ) )
216  result.push_back( msg );
217  }
218 }
219 
221 {
223 }
224 
226 {
228 }
229 
231 {
232  m_cache.setNextSenderMsgSeqNum( value );
233  setSeqNum();
234 }
235 
237 {
238  m_cache.setNextTargetMsgSeqNum( value );
239  setSeqNum();
240 }
241 
243 {
245  setSeqNum();
246 }
247 
249 {
251  setSeqNum();
252 }
253 
255 {
256  return m_cache.getCreationTime();
257 }
258 
260 {
261  try
262  {
263  m_cache.reset();
264  open( true );
265  setSession();
266  }
267  catch( std::exception& e )
268  {
269  throw IOException( e.what() );
270  }
271 }
272 
274 {
275  try
276  {
277  m_cache.reset();
278  open( false );
279  }
280  catch( std::exception& e )
281  {
282  throw IOException( e.what() );
283  }
284 }
285 
287 {
288  rewind( m_seqNumsFile );
289  fprintf( m_seqNumsFile, "%10.10d : %10.10d",
291  if ( ferror( m_seqNumsFile ) )
292  throw IOException( "Unable to write to file " + m_seqNumsFileName );
293  if ( fflush( m_seqNumsFile ) )
294  throw IOException( "Unable to flush file " + m_seqNumsFileName );
295 }
296 
298 {
299  rewind( m_sessionFile );
300  fprintf( m_sessionFile, "%s",
302  if ( ferror( m_sessionFile ) )
303  throw IOException( "Unable to write to file " + m_sessionFileName );
304  if ( fflush( m_sessionFile ) )
305  throw IOException( "Unable to flush file " + m_sessionFileName );
306 }
307 
308 bool FileStore::get( int msgSeqNum, std::string& msg ) const
309 throw ( IOException )
310 {
311  NumToOffset::const_iterator find = m_offsets.find( msgSeqNum );
312  if ( find == m_offsets.end() ) return false;
313  const OffsetSize& offset = find->second;
314  if ( fseek( m_msgFile, offset.first, SEEK_SET ) )
315  throw IOException( "Unable to seek in file " + m_msgFileName );
316  char* buffer = new char[ offset.second + 1 ];
317  size_t result = fread( buffer, sizeof( char ), offset.second, m_msgFile );
318  if ( ferror( m_msgFile ) || result != (size_t)offset.second )
319  {
320  delete [] buffer;
321  throw IOException( "Unable to read from file " + m_msgFileName );
322  }
323  buffer[ offset.second ] = 0;
324  msg = buffer;
325  delete [] buffer;
326  return true;
327 }
328 
329 } //namespace FIX
std::string m_sessionFileName
Definition: FileStore.h:120
FileStore(std::string, const SessionID &s)
Definition: FileStore.cpp:34
void incrNextSenderMsgSeqNum()
Definition: FileStore.cpp:242
virtual ~FileStore()
Definition: FileStore.cpp:71
static std::string convert(const UtcTimeStamp &value, bool showMilliseconds=false)
std::string m_msgFileName
Definition: FileStore.h:117
void setNextTargetMsgSeqNum(int value)
Definition: FileStore.cpp:236
int getNextTargetMsgSeqNum() const
Definition: FileStore.cpp:225
void incrNextSenderMsgSeqNum()
Definition: MessageStore.h:112
FILE * m_msgFile
Definition: FileStore.h:122
int getNextSenderMsgSeqNum() const
Definition: MessageStore.h:104
int getNextSenderMsgSeqNum() const
Definition: FileStore.cpp:220
#define FILE_FSCANF
Definition: Utility.h:178
std::string file_appendpath(const std::string &path, const std::string &file)
Definition: Utility.cpp:528
void open(bool deleteFile)
Definition: FileStore.cpp:79
int getNextTargetMsgSeqNum() const
Definition: MessageStore.h:106
void setNextSenderMsgSeqNum(int value)
Definition: MessageStore.h:108
void destroy(MessageStore *)
Definition: FileStore.cpp:176
const SenderCompID & getSenderCompID() const
Definition: SessionID.h:55
const char FILE_STORE_PATH[]
UtcTimeStamp getCreationTime() const
Definition: FileStore.cpp:254
const Dictionary & get(const SessionID &) const
Get a dictionary for a session.
bool set(int, const std::string &)
Definition: FileStore.cpp:181
SessionSettings m_settings
Definition: FileStore.h:51
void populateCache()
Definition: FileStore.cpp:126
void setNextTargetMsgSeqNum(int value)
Definition: MessageStore.h:110
MemoryStore m_cache
Definition: FileStore.h:114
std::string m_path
Definition: FileStore.h:50
std::string m_headerFileName
Definition: FileStore.h:118
File based implementation of MessageStore.
Definition: FileStore.h:81
Application is not configured correctly
Definition: Exceptions.h:87
void file_mkdir(const char *path)
Definition: Utility.cpp:466
void setSession()
Definition: FileStore.cpp:297
void incrNextTargetMsgSeqNum()
Definition: MessageStore.h:114
void file_unlink(const char *path)
Definition: Utility.cpp:514
void incrNextTargetMsgSeqNum()
Definition: FileStore.cpp:248
FILE * m_sessionFile
Definition: FileStore.h:125
std::string getString(const std::string &, bool capitalize=false) const
Get a value as a string.
Definition: Dictionary.cpp:32
This interface must be implemented to store and retrieve messages and sequence numbers.
Definition: MessageStore.h:66
void setSeqNum()
Definition: FileStore.cpp:286
void setNextSenderMsgSeqNum(int value)
Definition: FileStore.cpp:230
FILE * m_headerFile
Definition: FileStore.h:123
FILE * file_fopen(const char *path, const char *mode)
Definition: Utility.cpp:486
Date and Time represented in UTC.
Definition: FieldTypes.h:399
For storage and retrieval of key/value pairs.
Definition: Dictionary.h:36
void get(int, int, std::vector< std::string > &) const
Definition: FileStore.cpp:207
MessageStore * create(const SessionID &)
Definition: FileStore.cpp:166
Unique session id consists of BeginString, SenderCompID and TargetCompID.
Definition: SessionID.h:30
FILE * m_seqNumsFile
Definition: FileStore.h:124
NumToOffset m_offsets
Definition: FileStore.h:115
const BeginString & getBeginString() const
Definition: SessionID.h:53
UtcTimeStamp getCreationTime() const
Definition: MessageStore.h:119
const std::string & getSessionQualifier() const
Definition: SessionID.h:59
IO Error.
Definition: Exceptions.h:238
void setCreationTime(const UtcTimeStamp &creationTime)
Definition: MessageStore.h:117
const TargetCompID & getTargetCompID() const
Definition: SessionID.h:57
std::pair< int, int > OffsetSize
Definition: FileStore.h:103
std::string m_seqNumsFileName
Definition: FileStore.h:119

Generated on Sat Mar 29 2014 15:13:32 for QuickFIX by doxygen 1.8.5 written by Dimitri van Heesch, © 1997-2001