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
32namespace FIX
33{
34FileStore::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 =
47 s.getSessionQualifier();
48
49 std::string sessionid = begin + "-" + sender + "-" + target;
50 if( qualifier.size() )
51 sessionid += "-" + qualifier;
52
53 std::string prefix
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
78
79void FileStore::open( bool deleteFile )
80{
81 if ( m_msgFile ) fclose( m_msgFile );
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() );
97 }
98
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;
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 }
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 }
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 }
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
192bool FileStore::set( int msgSeqNum, const std::string& msg )
193throw ( 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
223void FileStore::get( int begin, int end,
224 std::vector < std::string > & result ) const
225throw ( 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
240
245
247{
248 m_cache.setNextSenderMsgSeqNum( value );
249 setSeqNum();
250}
251
253{
254 m_cache.setNextTargetMsgSeqNum( value );
255 setSeqNum();
256}
257
263
269
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{
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{
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
324bool FileStore::get( int msgSeqNum, std::string& msg ) const
325throw ( 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.
MessageStore * create(const SessionID &)
SessionSettings m_settings
Definition FileStore.h:51
std::string m_path
Definition FileStore.h:50
void destroy(MessageStore *)
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)
UtcTimeStamp getCreationTime() const
int getNextSenderMsgSeqNum() const
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()
void incrNextTargetMsgSeqNum()
std::string m_sessionFileName
Definition FileStore.h:124
void open(bool deleteFile)
Definition FileStore.cpp:79
void populateCache()
std::string m_headerFileName
Definition FileStore.h:122
void get(int, int, std::vector< std::string > &) const
virtual ~FileStore()
Definition FileStore.cpp:71
MemoryStore m_cache
Definition FileStore.h:118
void setNextTargetMsgSeqNum(int value)
std::string m_msgFileName
Definition FileStore.h:121
FileStore(std::string, const SessionID &s)
Definition FileStore.cpp:34
FILE * m_msgFile
Definition FileStore.h:126
NumToOffset m_offsets
Definition FileStore.h:119
bool set(int, const std::string &)
int getNextTargetMsgSeqNum() const
void setCreationTime(const UtcTimeStamp &creationTime)
int getNextTargetMsgSeqNum() const
void incrNextTargetMsgSeqNum()
void incrNextSenderMsgSeqNum()
void setNextTargetMsgSeqNum(int value)
UtcTimeStamp getCreationTime() const
void setNextSenderMsgSeqNum(int value)
int getNextSenderMsgSeqNum() const
This interface must be implemented to store and retrieve messages and sequence numbers.
Unique session id consists of BeginString, SenderCompID and TargetCompID.
Definition SessionID.h:31
const Dictionary & get(const SessionID &) const
Get a dictionary for a session.
Date and Time represented in UTC.
Definition FieldTypes.h:583
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 Mon Oct 14 2024 06:04:44 for QuickFIX by doxygen 1.9.8 written by Dimitri van Heesch, © 1997-2001