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;
132  long offset;
133  std::size_t size;
134 
135  while (FILE_FSCANF(headerFile, "%d,%ld,%lu ", &num, &offset, &size) == 3)
136  {
137  std::pair<NumToOffset::iterator, bool> it =
138  m_offsets.insert(NumToOffset::value_type(num, std::make_pair(offset, size)));
139  //std::cout << it.first->second.first << " --- " << it.first->second.second << '\n';
140  if (it.second == false)
141  {
142  it.first->second = std::make_pair(offset, size);
143  }
144  }
145  fclose( headerFile );
146  }
147 
148  FILE* seqNumsFile = file_fopen( m_seqNumsFileName.c_str(), "r+" );
149  if ( seqNumsFile )
150  {
151  int sender, target;
152  if ( FILE_FSCANF( seqNumsFile, "%d : %d", &sender, &target ) == 2 )
153  {
156  }
157  fclose( seqNumsFile );
158  }
159 
160  FILE* sessionFile = file_fopen( m_sessionFileName.c_str(), "r+" );
161  if ( sessionFile )
162  {
163  char time[ 22 ];
164 #ifdef HAVE_FSCANF_S
165  int result = FILE_FSCANF( sessionFile, "%s", time, 22 );
166 #else
167  int result = FILE_FSCANF( sessionFile, "%s", time );
168 #endif
169  if( result == 1 )
170  {
172  }
173  fclose( sessionFile );
174  }
175 }
176 
178 {
179  if ( m_path.size() ) return new FileStore( m_path, s );
180 
181  std::string path;
182  Dictionary settings = m_settings.get( s );
183  path = settings.getString( FILE_STORE_PATH );
184  return new FileStore( path, s );
185 }
186 
188 {
189  delete pStore;
190 }
191 
192 bool FileStore::set( int msgSeqNum, const std::string& msg )
193 throw ( IOException )
194 {
195  if ( fseek( m_msgFile, 0, SEEK_END ) )
196  throw IOException( "Cannot seek to end of " + m_msgFileName );
197  if ( fseek( m_headerFile, 0, SEEK_END ) )
198  throw IOException( "Cannot seek to end of " + m_headerFileName );
199 
200  long offset = ftell( m_msgFile );
201  if ( offset < 0 )
202  throw IOException( "Unable to get file pointer position from " + m_msgFileName );
203  std::size_t size = msg.size();
204 
205  if ( fprintf( m_headerFile, "%d,%ld,%lu ", msgSeqNum, offset, size ) < 0 )
206  throw IOException( "Unable to write to file " + m_headerFileName );
207  std::pair<NumToOffset::iterator, bool> it =
208  m_offsets.insert(NumToOffset::value_type(msgSeqNum, std::make_pair(offset, size)));
209  if (it.second == false)
210  {
211  it.first->second = std::make_pair(offset, size);
212  }
213  fwrite( msg.c_str(), sizeof( char ), msg.size(), m_msgFile );
214  if ( ferror( m_msgFile ) )
215  throw IOException( "Unable to write to file " + m_msgFileName );
216  if ( fflush( m_msgFile ) == EOF )
217  throw IOException( "Unable to flush file " + m_msgFileName );
218  if ( fflush( m_headerFile ) == EOF )
219  throw IOException( "Unable to flush file " + m_headerFileName );
220  return true;
221 }
222 
223 void FileStore::get( int begin, int end,
224  std::vector < std::string > & result ) const
225 throw ( IOException )
226 {
227  result.clear();
228  std::string msg;
229  for ( int i = begin; i <= end; ++i )
230  {
231  if ( get( i, msg ) )
232  result.push_back( msg );
233  }
234 }
235 
237 {
239 }
240 
242 {
244 }
245 
247 {
248  m_cache.setNextSenderMsgSeqNum( value );
249  setSeqNum();
250 }
251 
253 {
254  m_cache.setNextTargetMsgSeqNum( value );
255  setSeqNum();
256 }
257 
259 {
261  setSeqNum();
262 }
263 
265 {
267  setSeqNum();
268 }
269 
271 {
272  return m_cache.getCreationTime();
273 }
274 
276 {
277  try
278  {
279  m_cache.reset();
280  open( true );
281  setSession();
282  }
283  catch( std::exception& e )
284  {
285  throw IOException( e.what() );
286  }
287 }
288 
290 {
291  try
292  {
293  m_cache.reset();
294  open( false );
295  }
296  catch( std::exception& e )
297  {
298  throw IOException( e.what() );
299  }
300 }
301 
303 {
304  rewind( m_seqNumsFile );
305  fprintf( m_seqNumsFile, "%10.10d : %10.10d",
307  if ( ferror( m_seqNumsFile ) )
308  throw IOException( "Unable to write to file " + m_seqNumsFileName );
309  if ( fflush( m_seqNumsFile ) )
310  throw IOException( "Unable to flush file " + m_seqNumsFileName );
311 }
312 
314 {
315  rewind( m_sessionFile );
316  fprintf( m_sessionFile, "%s",
318  if ( ferror( m_sessionFile ) )
319  throw IOException( "Unable to write to file " + m_sessionFileName );
320  if ( fflush( m_sessionFile ) )
321  throw IOException( "Unable to flush file " + m_sessionFileName );
322 }
323 
324 bool FileStore::get( int msgSeqNum, std::string& msg ) const
325 throw ( IOException )
326 {
327  NumToOffset::const_iterator find = m_offsets.find( msgSeqNum );
328  if ( find == m_offsets.end() ) return false;
329  const OffsetSize& offset = find->second;
330  if ( fseek( m_msgFile, offset.first, SEEK_SET ) )
331  throw IOException( "Unable to seek in file " + m_msgFileName );
332  char* buffer = new char[ offset.second + 1 ];
333  size_t result = fread( buffer, sizeof( char ), offset.second, m_msgFile );
334  if ( ferror( m_msgFile ) || result != (size_t)offset.second )
335  {
336  delete [] buffer;
337  throw IOException( "Unable to read from file " + m_msgFileName );
338  }
339  buffer[ offset.second ] = 0;
340  msg = buffer;
341  delete [] buffer;
342  return true;
343 }
344 
345 } //namespace FIX
#define FILE_FSCANF
Definition: Utility.h:215
For storage and retrieval of key/value pairs.
Definition: Dictionary.h:37
std::string getString(const std::string &, bool capitalize=false) const
Get a value as a string.
Definition: Dictionary.cpp:32
MessageStore * create(const SessionID &)
Definition: FileStore.cpp:177
SessionSettings m_settings
Definition: FileStore.h:51
std::string m_path
Definition: FileStore.h:50
void destroy(MessageStore *)
Definition: FileStore.cpp:187
File based implementation of MessageStore.
Definition: FileStore.h:82
FILE * m_headerFile
Definition: FileStore.h:127
std::string m_seqNumsFileName
Definition: FileStore.h:123
void setNextSenderMsgSeqNum(int value)
Definition: FileStore.cpp:246
UtcTimeStamp getCreationTime() const
Definition: FileStore.cpp:270
int getNextSenderMsgSeqNum() const
Definition: FileStore.cpp:236
std::pair< long, std::size_t > OffsetSize
Definition: FileStore.h:106
FILE * m_sessionFile
Definition: FileStore.h:129
FILE * m_seqNumsFile
Definition: FileStore.h:128
void incrNextSenderMsgSeqNum()
Definition: FileStore.cpp:258
void setSession()
Definition: FileStore.cpp:313
void incrNextTargetMsgSeqNum()
Definition: FileStore.cpp:264
std::string m_sessionFileName
Definition: FileStore.h:124
void open(bool deleteFile)
Definition: FileStore.cpp:79
void populateCache()
Definition: FileStore.cpp:126
std::string m_headerFileName
Definition: FileStore.h:122
void get(int, int, std::vector< std::string > &) const
Definition: FileStore.cpp:223
virtual ~FileStore()
Definition: FileStore.cpp:71
MemoryStore m_cache
Definition: FileStore.h:118
void setNextTargetMsgSeqNum(int value)
Definition: FileStore.cpp:252
std::string m_msgFileName
Definition: FileStore.h:121
FileStore(std::string, const SessionID &s)
Definition: FileStore.cpp:34
void setSeqNum()
Definition: FileStore.cpp:302
FILE * m_msgFile
Definition: FileStore.h:126
NumToOffset m_offsets
Definition: FileStore.h:119
bool set(int, const std::string &)
Definition: FileStore.cpp:192
int getNextTargetMsgSeqNum() const
Definition: FileStore.cpp:241
void setCreationTime(const UtcTimeStamp &creationTime)
Definition: MessageStore.h:117
int getNextTargetMsgSeqNum() const
Definition: MessageStore.h:106
void incrNextTargetMsgSeqNum()
Definition: MessageStore.h:114
void incrNextSenderMsgSeqNum()
Definition: MessageStore.h:112
void setNextTargetMsgSeqNum(int value)
Definition: MessageStore.h:110
UtcTimeStamp getCreationTime() const
Definition: MessageStore.h:119
void setNextSenderMsgSeqNum(int value)
Definition: MessageStore.h:108
int getNextSenderMsgSeqNum() const
Definition: MessageStore.h:104
This interface must be implemented to store and retrieve messages and sequence numbers.
Definition: MessageStore.h:67
Unique session id consists of BeginString, SenderCompID and TargetCompID.
Definition: SessionID.h:31
const TargetCompID & getTargetCompID() const
Definition: SessionID.h:57
const std::string & getSessionQualifier() const
Definition: SessionID.h:59
const BeginString & getBeginString() const
Definition: SessionID.h:53
const SenderCompID & getSenderCompID() const
Definition: SessionID.h:55
const Dictionary & get(const SessionID &) const
Get a dictionary for a session.
Date and Time represented in UTC.
Definition: FieldTypes.h:583
Definition: Acceptor.cpp:35
void file_unlink(const char *path)
Definition: Utility.cpp:537
void file_mkdir(const char *path)
Definition: Utility.cpp:489
const char FILE_STORE_PATH[]
FILE * file_fopen(const char *path, const char *mode)
Definition: Utility.cpp:509
std::string file_appendpath(const std::string &path, const std::string &file)
Definition: Utility.cpp:551
Application is not configured correctly
Definition: Exceptions.h:88
static std::string convert(const UtcTimeStamp &value, int precision=0)

Generated on Wed Nov 24 2021 09:55:53 for QuickFIX by doxygen 1.9.1 written by Dimitri van Heesch, © 1997-2001