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

Generated on Thu Sep 5 2019 11:07:58 for QuickFIX by doxygen 1.8.13 written by Dimitri van Heesch, © 1997-2001