quickfix_ruby_ud 2.0.7-x86_64-linux
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/ext/quickfix/Acceptor.cpp +257 -0
- data/ext/quickfix/Acceptor.h +127 -0
- data/ext/quickfix/Allocator.h +9 -0
- data/ext/quickfix/Application.h +137 -0
- data/ext/quickfix/DOMDocument.h +70 -0
- data/ext/quickfix/DataDictionary.cpp +679 -0
- data/ext/quickfix/DataDictionary.h +607 -0
- data/ext/quickfix/DataDictionaryProvider.cpp +66 -0
- data/ext/quickfix/DataDictionaryProvider.h +67 -0
- data/ext/quickfix/DatabaseConnectionID.h +98 -0
- data/ext/quickfix/DatabaseConnectionPool.h +84 -0
- data/ext/quickfix/Dictionary.cpp +157 -0
- data/ext/quickfix/Dictionary.h +89 -0
- data/ext/quickfix/Event.h +89 -0
- data/ext/quickfix/Except.h +39 -0
- data/ext/quickfix/Exceptions.h +257 -0
- data/ext/quickfix/Field.h +654 -0
- data/ext/quickfix/FieldConvertors.cpp +86 -0
- data/ext/quickfix/FieldConvertors.h +800 -0
- data/ext/quickfix/FieldMap.cpp +254 -0
- data/ext/quickfix/FieldMap.h +327 -0
- data/ext/quickfix/FieldNumbers.h +44 -0
- data/ext/quickfix/FieldTypes.cpp +62 -0
- data/ext/quickfix/FieldTypes.h +817 -0
- data/ext/quickfix/Fields.h +30 -0
- data/ext/quickfix/FileLog.cpp +176 -0
- data/ext/quickfix/FileLog.h +110 -0
- data/ext/quickfix/FileStore.cpp +369 -0
- data/ext/quickfix/FileStore.h +131 -0
- data/ext/quickfix/FixCommonFields.h +13 -0
- data/ext/quickfix/FixFieldNumbers.h +6132 -0
- data/ext/quickfix/FixFields.h +6133 -0
- data/ext/quickfix/FixValues.h +5790 -0
- data/ext/quickfix/Group.cpp +44 -0
- data/ext/quickfix/Group.h +78 -0
- data/ext/quickfix/HostDetailsProvider.cpp +79 -0
- data/ext/quickfix/HostDetailsProvider.h +44 -0
- data/ext/quickfix/HtmlBuilder.h +178 -0
- data/ext/quickfix/HttpConnection.cpp +914 -0
- data/ext/quickfix/HttpConnection.h +74 -0
- data/ext/quickfix/HttpMessage.cpp +229 -0
- data/ext/quickfix/HttpMessage.h +112 -0
- data/ext/quickfix/HttpParser.cpp +49 -0
- data/ext/quickfix/HttpParser.h +49 -0
- data/ext/quickfix/HttpServer.cpp +152 -0
- data/ext/quickfix/HttpServer.h +76 -0
- data/ext/quickfix/Initiator.cpp +310 -0
- data/ext/quickfix/Initiator.h +151 -0
- data/ext/quickfix/Log.cpp +71 -0
- data/ext/quickfix/Log.h +254 -0
- data/ext/quickfix/Message.cpp +617 -0
- data/ext/quickfix/Message.h +419 -0
- data/ext/quickfix/MessageCracker.h +171 -0
- data/ext/quickfix/MessageSorters.cpp +101 -0
- data/ext/quickfix/MessageSorters.h +185 -0
- data/ext/quickfix/MessageStore.cpp +182 -0
- data/ext/quickfix/MessageStore.h +164 -0
- data/ext/quickfix/Mutex.h +120 -0
- data/ext/quickfix/MySQLConnection.h +187 -0
- data/ext/quickfix/MySQLLog.cpp +262 -0
- data/ext/quickfix/MySQLLog.h +158 -0
- data/ext/quickfix/MySQLStore.cpp +323 -0
- data/ext/quickfix/MySQLStore.h +161 -0
- data/ext/quickfix/MySQLStubs.h +203 -0
- data/ext/quickfix/NullStore.cpp +40 -0
- data/ext/quickfix/NullStore.h +89 -0
- data/ext/quickfix/OdbcConnection.h +241 -0
- data/ext/quickfix/OdbcLog.cpp +230 -0
- data/ext/quickfix/OdbcLog.h +109 -0
- data/ext/quickfix/OdbcStore.cpp +313 -0
- data/ext/quickfix/OdbcStore.h +124 -0
- data/ext/quickfix/PUGIXML_DOMDocument.cpp +112 -0
- data/ext/quickfix/PUGIXML_DOMDocument.h +81 -0
- data/ext/quickfix/Parser.cpp +111 -0
- data/ext/quickfix/Parser.h +50 -0
- data/ext/quickfix/PostgreSQLConnection.h +163 -0
- data/ext/quickfix/PostgreSQLLog.cpp +263 -0
- data/ext/quickfix/PostgreSQLLog.h +157 -0
- data/ext/quickfix/PostgreSQLStore.cpp +327 -0
- data/ext/quickfix/PostgreSQLStore.h +160 -0
- data/ext/quickfix/PostgreSQLStubs.h +203 -0
- data/ext/quickfix/Queue.h +66 -0
- data/ext/quickfix/QuickfixRuby.cpp +131900 -0
- data/ext/quickfix/QuickfixRuby.h +56 -0
- data/ext/quickfix/Responder.h +41 -0
- data/ext/quickfix/SSLSocketAcceptor.cpp +409 -0
- data/ext/quickfix/SSLSocketAcceptor.h +186 -0
- data/ext/quickfix/SSLSocketConnection.cpp +434 -0
- data/ext/quickfix/SSLSocketConnection.h +221 -0
- data/ext/quickfix/SSLSocketInitiator.cpp +558 -0
- data/ext/quickfix/SSLSocketInitiator.h +203 -0
- data/ext/quickfix/SSLStubs.h +129 -0
- data/ext/quickfix/Session.cpp +1437 -0
- data/ext/quickfix/Session.h +343 -0
- data/ext/quickfix/SessionFactory.cpp +314 -0
- data/ext/quickfix/SessionFactory.h +84 -0
- data/ext/quickfix/SessionID.h +136 -0
- data/ext/quickfix/SessionSettings.cpp +165 -0
- data/ext/quickfix/SessionSettings.h +283 -0
- data/ext/quickfix/SessionState.h +260 -0
- data/ext/quickfix/Settings.cpp +160 -0
- data/ext/quickfix/Settings.h +56 -0
- data/ext/quickfix/SharedArray.h +274 -0
- data/ext/quickfix/SocketAcceptor.cpp +216 -0
- data/ext/quickfix/SocketAcceptor.h +77 -0
- data/ext/quickfix/SocketConnection.cpp +256 -0
- data/ext/quickfix/SocketConnection.h +102 -0
- data/ext/quickfix/SocketConnector.cpp +112 -0
- data/ext/quickfix/SocketConnector.h +76 -0
- data/ext/quickfix/SocketInitiator.cpp +241 -0
- data/ext/quickfix/SocketInitiator.h +76 -0
- data/ext/quickfix/SocketMonitor.h +26 -0
- data/ext/quickfix/SocketMonitor_UNIX.cpp +238 -0
- data/ext/quickfix/SocketMonitor_UNIX.h +101 -0
- data/ext/quickfix/SocketMonitor_WIN32.cpp +248 -0
- data/ext/quickfix/SocketMonitor_WIN32.h +99 -0
- data/ext/quickfix/SocketServer.cpp +163 -0
- data/ext/quickfix/SocketServer.h +100 -0
- data/ext/quickfix/ThreadedSSLSocketAcceptor.cpp +436 -0
- data/ext/quickfix/ThreadedSSLSocketAcceptor.h +209 -0
- data/ext/quickfix/ThreadedSSLSocketConnection.cpp +364 -0
- data/ext/quickfix/ThreadedSSLSocketConnection.h +191 -0
- data/ext/quickfix/ThreadedSSLSocketInitiator.cpp +434 -0
- data/ext/quickfix/ThreadedSSLSocketInitiator.h +193 -0
- data/ext/quickfix/ThreadedSocketAcceptor.cpp +242 -0
- data/ext/quickfix/ThreadedSocketAcceptor.h +95 -0
- data/ext/quickfix/ThreadedSocketConnection.cpp +227 -0
- data/ext/quickfix/ThreadedSocketConnection.h +89 -0
- data/ext/quickfix/ThreadedSocketInitiator.cpp +238 -0
- data/ext/quickfix/ThreadedSocketInitiator.h +78 -0
- data/ext/quickfix/TimeRange.cpp +227 -0
- data/ext/quickfix/TimeRange.h +215 -0
- data/ext/quickfix/Utility.cpp +639 -0
- data/ext/quickfix/Utility.h +255 -0
- data/ext/quickfix/UtilitySSL.cpp +1612 -0
- data/ext/quickfix/UtilitySSL.h +274 -0
- data/ext/quickfix/Values.h +63 -0
- data/ext/quickfix/config-all.h +10 -0
- data/ext/quickfix/config.h +10 -0
- data/ext/quickfix/config_unix.h +178 -0
- data/ext/quickfix/config_windows.h +0 -0
- data/ext/quickfix/dirent_windows.h +838 -0
- data/ext/quickfix/double-conversion/bignum-dtoa.cc +641 -0
- data/ext/quickfix/double-conversion/bignum-dtoa.h +84 -0
- data/ext/quickfix/double-conversion/bignum.cc +766 -0
- data/ext/quickfix/double-conversion/bignum.h +144 -0
- data/ext/quickfix/double-conversion/cached-powers.cc +176 -0
- data/ext/quickfix/double-conversion/cached-powers.h +64 -0
- data/ext/quickfix/double-conversion/diy-fp.cc +57 -0
- data/ext/quickfix/double-conversion/diy-fp.h +118 -0
- data/ext/quickfix/double-conversion/double-conversion.cc +994 -0
- data/ext/quickfix/double-conversion/double-conversion.h +543 -0
- data/ext/quickfix/double-conversion/fast-dtoa.cc +665 -0
- data/ext/quickfix/double-conversion/fast-dtoa.h +88 -0
- data/ext/quickfix/double-conversion/fixed-dtoa.cc +404 -0
- data/ext/quickfix/double-conversion/fixed-dtoa.h +56 -0
- data/ext/quickfix/double-conversion/ieee.h +402 -0
- data/ext/quickfix/double-conversion/strtod.cc +557 -0
- data/ext/quickfix/double-conversion/strtod.h +45 -0
- data/ext/quickfix/double-conversion/utils.h +374 -0
- data/ext/quickfix/extconf.rb +76 -0
- data/ext/quickfix/index.h +37 -0
- data/ext/quickfix/pugiconfig.hpp +77 -0
- data/ext/quickfix/pugixml.cpp +13237 -0
- data/ext/quickfix/pugixml.hpp +1516 -0
- data/ext/quickfix/scope_guard.hpp +215 -0
- data/ext/quickfix/stdint_msvc.h +254 -0
- data/ext/quickfix/strptime.h +7 -0
- data/lib/2.4/quickfix.so +0 -0
- data/lib/2.5/quickfix.so +0 -0
- data/lib/2.6/quickfix.so +0 -0
- data/lib/2.7/quickfix.so +0 -0
- data/lib/3.0/quickfix.so +0 -0
- data/lib/3.1/quickfix.so +0 -0
- data/lib/3.2/quickfix.so +0 -0
- data/lib/3.3/quickfix.so +0 -0
- data/lib/3.4/quickfix.so +0 -0
- data/lib/quickfix40.rb +274 -0
- data/lib/quickfix41.rb +351 -0
- data/lib/quickfix42.rb +1184 -0
- data/lib/quickfix43.rb +3504 -0
- data/lib/quickfix44.rb +14040 -0
- data/lib/quickfix50.rb +20051 -0
- data/lib/quickfix50sp1.rb +23596 -0
- data/lib/quickfix50sp2.rb +412444 -0
- data/lib/quickfix_fields.rb +79393 -0
- data/lib/quickfix_ruby.rb +82 -0
- data/lib/quickfixt11.rb +65 -0
- data/spec/FIX40.xml +862 -0
- data/spec/FIX41.xml +1282 -0
- data/spec/FIX42.xml +2743 -0
- data/spec/FIX43.xml +4230 -0
- data/spec/FIX44.xml +6600 -0
- data/spec/FIX50.xml +8142 -0
- data/spec/FIX50SP1.xml +9506 -0
- data/spec/FIX50SP2.xml +26069 -0
- data/spec/FIXT11.xml +252 -0
- data/test/DataDictionaryTestCase.rb +268 -0
- data/test/DictionaryTestCase.rb +112 -0
- data/test/FieldBaseTestCase.rb +24 -0
- data/test/MessageStoreTestCase.rb +19 -0
- data/test/MessageTestCase.rb +368 -0
- data/test/SessionSettingsTestCase.rb +41 -0
- metadata +247 -0
@@ -0,0 +1,30 @@
|
|
1
|
+
/* -*- C++ -*- */
|
2
|
+
|
3
|
+
/****************************************************************************
|
4
|
+
** Copyright (c) 2001-2014
|
5
|
+
**
|
6
|
+
** This file is part of the QuickFIX FIX Engine
|
7
|
+
**
|
8
|
+
** This file may be distributed under the terms of the quickfixengine.org
|
9
|
+
** license as defined by quickfixengine.org and appearing in the file
|
10
|
+
** LICENSE included in the packaging of this file.
|
11
|
+
**
|
12
|
+
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
13
|
+
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
14
|
+
**
|
15
|
+
** See http://www.quickfixengine.org/LICENSE for licensing information.
|
16
|
+
**
|
17
|
+
** Contact ask@quickfixengine.org if any conditions of this licensing are
|
18
|
+
** not clear to you.
|
19
|
+
**
|
20
|
+
****************************************************************************/
|
21
|
+
|
22
|
+
#ifndef FIX_FIELDS_BASE_H
|
23
|
+
#define FIX_FIELDS_BASE_H
|
24
|
+
|
25
|
+
#include "Field.h"
|
26
|
+
#include "FixFields.h"
|
27
|
+
|
28
|
+
#undef Yield
|
29
|
+
|
30
|
+
#endif // FIX_FIELDS_BASE_H
|
@@ -0,0 +1,176 @@
|
|
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 "FileLog.h"
|
27
|
+
|
28
|
+
namespace FIX {
|
29
|
+
Log *FileLogFactory::create() {
|
30
|
+
if (++m_globalLogCount > 1) {
|
31
|
+
return m_globalLog;
|
32
|
+
}
|
33
|
+
|
34
|
+
if (m_path.size()) {
|
35
|
+
return new FileLog(m_path);
|
36
|
+
}
|
37
|
+
|
38
|
+
try {
|
39
|
+
|
40
|
+
const Dictionary &settings = m_settings.get();
|
41
|
+
std::string path = settings.getString(FILE_LOG_PATH);
|
42
|
+
std::string backupPath = path;
|
43
|
+
|
44
|
+
if (settings.has(FILE_LOG_BACKUP_PATH)) {
|
45
|
+
backupPath = settings.getString(FILE_LOG_BACKUP_PATH);
|
46
|
+
}
|
47
|
+
|
48
|
+
return m_globalLog = new FileLog(path, backupPath);
|
49
|
+
} catch (ConfigError &) {
|
50
|
+
m_globalLogCount--;
|
51
|
+
throw;
|
52
|
+
}
|
53
|
+
}
|
54
|
+
|
55
|
+
Log *FileLogFactory::create(const SessionID &s) {
|
56
|
+
if (m_path.size() && m_backupPath.size()) {
|
57
|
+
return new FileLog(m_path, m_backupPath, s);
|
58
|
+
}
|
59
|
+
if (m_path.size()) {
|
60
|
+
return new FileLog(m_path, s);
|
61
|
+
}
|
62
|
+
|
63
|
+
std::string path;
|
64
|
+
std::string backupPath;
|
65
|
+
Dictionary settings = m_settings.get(s);
|
66
|
+
path = settings.getString(FILE_LOG_PATH);
|
67
|
+
backupPath = path;
|
68
|
+
if (settings.has(FILE_LOG_BACKUP_PATH)) {
|
69
|
+
backupPath = settings.getString(FILE_LOG_BACKUP_PATH);
|
70
|
+
}
|
71
|
+
|
72
|
+
return new FileLog(path, backupPath, s);
|
73
|
+
}
|
74
|
+
|
75
|
+
void FileLogFactory::destroy(Log *pLog) {
|
76
|
+
if (pLog != m_globalLog || --m_globalLogCount == 0) {
|
77
|
+
delete pLog;
|
78
|
+
}
|
79
|
+
}
|
80
|
+
|
81
|
+
FileLog::FileLog(const std::string &path) { init(path, path, "GLOBAL"); }
|
82
|
+
|
83
|
+
FileLog::FileLog(const std::string &path, const std::string &backupPath) { init(path, backupPath, "GLOBAL"); }
|
84
|
+
|
85
|
+
FileLog::FileLog(const std::string &path, const SessionID &s) { init(path, path, generatePrefix(s)); }
|
86
|
+
|
87
|
+
FileLog::FileLog(const std::string &path, const std::string &backupPath, const SessionID &s) {
|
88
|
+
init(path, backupPath, generatePrefix(s));
|
89
|
+
}
|
90
|
+
|
91
|
+
std::string FileLog::generatePrefix(const SessionID &s) {
|
92
|
+
const std::string &begin = s.getBeginString().getString();
|
93
|
+
const std::string &sender = s.getSenderCompID().getString();
|
94
|
+
const std::string &target = s.getTargetCompID().getString();
|
95
|
+
const std::string &qualifier = s.getSessionQualifier();
|
96
|
+
|
97
|
+
std::string prefix = begin + "-" + sender + "-" + target;
|
98
|
+
if (qualifier.size()) {
|
99
|
+
prefix += "-" + qualifier;
|
100
|
+
}
|
101
|
+
|
102
|
+
return prefix;
|
103
|
+
}
|
104
|
+
|
105
|
+
void FileLog::init(std::string path, std::string backupPath, const std::string &prefix) {
|
106
|
+
file_mkdir(path.c_str());
|
107
|
+
file_mkdir(backupPath.c_str());
|
108
|
+
|
109
|
+
if (path.empty()) {
|
110
|
+
path = ".";
|
111
|
+
}
|
112
|
+
if (backupPath.empty()) {
|
113
|
+
backupPath = path;
|
114
|
+
}
|
115
|
+
|
116
|
+
m_fullPrefix = file_appendpath(path, prefix + ".");
|
117
|
+
m_fullBackupPrefix = file_appendpath(backupPath, prefix + ".");
|
118
|
+
|
119
|
+
m_messagesFileName = m_fullPrefix + "messages.current.log";
|
120
|
+
m_eventFileName = m_fullPrefix + "event.current.log";
|
121
|
+
|
122
|
+
m_messages.open(m_messagesFileName.c_str(), std::ios::out | std::ios::app);
|
123
|
+
if (!m_messages.is_open()) {
|
124
|
+
throw ConfigError("Could not open messages file: " + m_messagesFileName);
|
125
|
+
}
|
126
|
+
m_event.open(m_eventFileName.c_str(), std::ios::out | std::ios::app);
|
127
|
+
if (!m_event.is_open()) {
|
128
|
+
throw ConfigError("Could not open event file: " + m_eventFileName);
|
129
|
+
}
|
130
|
+
}
|
131
|
+
|
132
|
+
FileLog::~FileLog() {
|
133
|
+
m_messages.close();
|
134
|
+
m_event.close();
|
135
|
+
}
|
136
|
+
|
137
|
+
void FileLog::clear() {
|
138
|
+
m_messages.close();
|
139
|
+
m_event.close();
|
140
|
+
|
141
|
+
m_messages.open(m_messagesFileName.c_str(), std::ios::out | std::ios::trunc);
|
142
|
+
m_event.open(m_eventFileName.c_str(), std::ios::out | std::ios::trunc);
|
143
|
+
}
|
144
|
+
|
145
|
+
void FileLog::backup() {
|
146
|
+
m_messages.close();
|
147
|
+
m_event.close();
|
148
|
+
|
149
|
+
int i = 0;
|
150
|
+
while (true) {
|
151
|
+
std::stringstream messagesFileName;
|
152
|
+
std::stringstream eventFileName;
|
153
|
+
|
154
|
+
messagesFileName << m_fullBackupPrefix << "messages.backup." << ++i << ".log";
|
155
|
+
eventFileName << m_fullBackupPrefix << "event.backup." << i << ".log";
|
156
|
+
FILE *messagesLogFile = file_fopen(messagesFileName.str().c_str(), "r");
|
157
|
+
FILE *eventLogFile = file_fopen(eventFileName.str().c_str(), "r");
|
158
|
+
|
159
|
+
if (messagesLogFile == NULL && eventLogFile == NULL) {
|
160
|
+
file_rename(m_messagesFileName.c_str(), messagesFileName.str().c_str());
|
161
|
+
file_rename(m_eventFileName.c_str(), eventFileName.str().c_str());
|
162
|
+
m_messages.open(m_messagesFileName.c_str(), std::ios::out | std::ios::trunc);
|
163
|
+
m_event.open(m_eventFileName.c_str(), std::ios::out | std::ios::trunc);
|
164
|
+
return;
|
165
|
+
}
|
166
|
+
|
167
|
+
if (messagesLogFile != NULL) {
|
168
|
+
file_fclose(messagesLogFile);
|
169
|
+
}
|
170
|
+
if (eventLogFile != NULL) {
|
171
|
+
file_fclose(eventLogFile);
|
172
|
+
}
|
173
|
+
}
|
174
|
+
}
|
175
|
+
|
176
|
+
} // namespace FIX
|
@@ -0,0 +1,110 @@
|
|
1
|
+
/* -*- C++ -*- */
|
2
|
+
|
3
|
+
/****************************************************************************
|
4
|
+
** Copyright (c) 2001-2014
|
5
|
+
**
|
6
|
+
** This file is part of the QuickFIX FIX Engine
|
7
|
+
**
|
8
|
+
** This file may be distributed under the terms of the quickfixengine.org
|
9
|
+
** license as defined by quickfixengine.org and appearing in the file
|
10
|
+
** LICENSE included in the packaging of this file.
|
11
|
+
**
|
12
|
+
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
13
|
+
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
14
|
+
**
|
15
|
+
** See http://www.quickfixengine.org/LICENSE for licensing information.
|
16
|
+
**
|
17
|
+
** Contact ask@quickfixengine.org if any conditions of this licensing are
|
18
|
+
** not clear to you.
|
19
|
+
**
|
20
|
+
****************************************************************************/
|
21
|
+
|
22
|
+
#ifndef FIX_FILELOG_H
|
23
|
+
#define FIX_FILELOG_H
|
24
|
+
|
25
|
+
#ifdef _MSC_VER
|
26
|
+
#pragma warning(disable : 4503 4355 4786 4290)
|
27
|
+
#endif
|
28
|
+
|
29
|
+
#include "Log.h"
|
30
|
+
#include "SessionSettings.h"
|
31
|
+
#include <fstream>
|
32
|
+
|
33
|
+
namespace FIX {
|
34
|
+
/**
|
35
|
+
* Creates a file based implementation of Log
|
36
|
+
*
|
37
|
+
* This stores all log events into flat files
|
38
|
+
*/
|
39
|
+
class FileLogFactory : public LogFactory {
|
40
|
+
public:
|
41
|
+
FileLogFactory(const SessionSettings &settings)
|
42
|
+
: m_settings(settings),
|
43
|
+
m_globalLog(0),
|
44
|
+
m_globalLogCount(0) {};
|
45
|
+
FileLogFactory(const std::string &path)
|
46
|
+
: m_path(path),
|
47
|
+
m_backupPath(path),
|
48
|
+
m_globalLog(0),
|
49
|
+
m_globalLogCount(0) {};
|
50
|
+
FileLogFactory(const std::string &path, const std::string &backupPath)
|
51
|
+
: m_path(path),
|
52
|
+
m_backupPath(backupPath),
|
53
|
+
m_globalLog(0),
|
54
|
+
m_globalLogCount(0) {};
|
55
|
+
|
56
|
+
public:
|
57
|
+
Log *create();
|
58
|
+
Log *create(const SessionID &);
|
59
|
+
void destroy(Log *log);
|
60
|
+
|
61
|
+
private:
|
62
|
+
std::string m_path;
|
63
|
+
std::string m_backupPath;
|
64
|
+
SessionSettings m_settings;
|
65
|
+
Log *m_globalLog;
|
66
|
+
int m_globalLogCount;
|
67
|
+
};
|
68
|
+
|
69
|
+
/**
|
70
|
+
* File based implementation of Log
|
71
|
+
*
|
72
|
+
* Two files are created by this implementation. One for messages,
|
73
|
+
* and one for events.
|
74
|
+
*
|
75
|
+
*/
|
76
|
+
class FileLog : public Log {
|
77
|
+
public:
|
78
|
+
FileLog(const std::string &path);
|
79
|
+
FileLog(const std::string &path, const std::string &backupPath);
|
80
|
+
FileLog(const std::string &path, const SessionID &sessionID);
|
81
|
+
FileLog(const std::string &path, const std::string &backupPath, const SessionID &sessionID);
|
82
|
+
virtual ~FileLog();
|
83
|
+
|
84
|
+
void clear();
|
85
|
+
void backup();
|
86
|
+
|
87
|
+
void onIncoming(const std::string &value) {
|
88
|
+
m_messages << UtcTimeStampConvertor::convert(UtcTimeStamp::now(), 9) << " : " << value << std::endl;
|
89
|
+
}
|
90
|
+
void onOutgoing(const std::string &value) {
|
91
|
+
m_messages << UtcTimeStampConvertor::convert(UtcTimeStamp::now(), 9) << " : " << value << std::endl;
|
92
|
+
}
|
93
|
+
void onEvent(const std::string &value) {
|
94
|
+
m_event << UtcTimeStampConvertor::convert(UtcTimeStamp::now(), 9) << " : " << value << std::endl;
|
95
|
+
}
|
96
|
+
|
97
|
+
private:
|
98
|
+
std::string generatePrefix(const SessionID &sessionID);
|
99
|
+
void init(std::string path, std::string backupPath, const std::string &prefix);
|
100
|
+
|
101
|
+
std::ofstream m_messages;
|
102
|
+
std::ofstream m_event;
|
103
|
+
std::string m_messagesFileName;
|
104
|
+
std::string m_eventFileName;
|
105
|
+
std::string m_fullPrefix;
|
106
|
+
std::string m_fullBackupPrefix;
|
107
|
+
};
|
108
|
+
} // namespace FIX
|
109
|
+
|
110
|
+
#endif // FIX_LOG_H
|
@@ -0,0 +1,369 @@
|
|
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 "Parser.h"
|
28
|
+
#include "SessionID.h"
|
29
|
+
#include "Utility.h"
|
30
|
+
#include <fstream>
|
31
|
+
#include <inttypes.h>
|
32
|
+
#include <sys/stat.h>
|
33
|
+
|
34
|
+
namespace {
|
35
|
+
auto const seqNumFileFormat = "%" + std::to_string(std::numeric_limits<uint64_t>::digits10 + 1) + "."
|
36
|
+
+ std::to_string(std::numeric_limits<uint64_t>::digits10 + 1) + SCNu64;
|
37
|
+
|
38
|
+
auto const seqNumPairFileFormat = (seqNumFileFormat + " : " + seqNumFileFormat);
|
39
|
+
|
40
|
+
auto constexpr sizeOf64BitSeqNumFile = 43;
|
41
|
+
} // namespace
|
42
|
+
namespace FIX {
|
43
|
+
FileStore::FileStore(const UtcTimeStamp &now, std::string path, const SessionID &sessionID)
|
44
|
+
: m_cache(now),
|
45
|
+
m_msgFile(0),
|
46
|
+
m_headerFile(0),
|
47
|
+
m_seqNumsFile(0),
|
48
|
+
m_sessionFile(0) {
|
49
|
+
file_mkdir(path.c_str());
|
50
|
+
|
51
|
+
if (path.empty()) {
|
52
|
+
path = ".";
|
53
|
+
}
|
54
|
+
const std::string &begin = sessionID.getBeginString().getString();
|
55
|
+
const std::string &sender = sessionID.getSenderCompID().getString();
|
56
|
+
const std::string &target = sessionID.getTargetCompID().getString();
|
57
|
+
const std::string &qualifier = sessionID.getSessionQualifier();
|
58
|
+
|
59
|
+
std::string sessionid = begin + "-" + sender + "-" + target;
|
60
|
+
if (qualifier.size()) {
|
61
|
+
sessionid += "-" + qualifier;
|
62
|
+
}
|
63
|
+
|
64
|
+
std::string prefix = file_appendpath(path, sessionid + ".");
|
65
|
+
|
66
|
+
m_msgFileName = prefix + "body";
|
67
|
+
m_headerFileName = prefix + "header";
|
68
|
+
m_seqNumsFileName = prefix + "seqnums";
|
69
|
+
m_sessionFileName = prefix + "session";
|
70
|
+
|
71
|
+
try {
|
72
|
+
open(false);
|
73
|
+
} catch (IOException &e) {
|
74
|
+
throw ConfigError(e.what());
|
75
|
+
}
|
76
|
+
}
|
77
|
+
|
78
|
+
FileStore::~FileStore() {
|
79
|
+
if (m_msgFile) {
|
80
|
+
fclose(m_msgFile);
|
81
|
+
}
|
82
|
+
if (m_headerFile) {
|
83
|
+
fclose(m_headerFile);
|
84
|
+
}
|
85
|
+
if (m_seqNumsFile) {
|
86
|
+
fclose(m_seqNumsFile);
|
87
|
+
}
|
88
|
+
if (m_sessionFile) {
|
89
|
+
fclose(m_sessionFile);
|
90
|
+
}
|
91
|
+
}
|
92
|
+
|
93
|
+
void FileStore::open(bool deleteFile) {
|
94
|
+
if (m_msgFile) {
|
95
|
+
fclose(m_msgFile);
|
96
|
+
}
|
97
|
+
if (m_headerFile) {
|
98
|
+
fclose(m_headerFile);
|
99
|
+
}
|
100
|
+
if (m_seqNumsFile) {
|
101
|
+
fclose(m_seqNumsFile);
|
102
|
+
}
|
103
|
+
if (m_sessionFile) {
|
104
|
+
fclose(m_sessionFile);
|
105
|
+
}
|
106
|
+
|
107
|
+
m_msgFile = 0;
|
108
|
+
m_headerFile = 0;
|
109
|
+
m_seqNumsFile = 0;
|
110
|
+
m_sessionFile = 0;
|
111
|
+
|
112
|
+
if (deleteFile) {
|
113
|
+
file_unlink(m_msgFileName.c_str());
|
114
|
+
file_unlink(m_headerFileName.c_str());
|
115
|
+
file_unlink(m_seqNumsFileName.c_str());
|
116
|
+
file_unlink(m_sessionFileName.c_str());
|
117
|
+
}
|
118
|
+
|
119
|
+
populateCache();
|
120
|
+
m_msgFile = file_fopen(m_msgFileName.c_str(), "r+");
|
121
|
+
if (!m_msgFile) {
|
122
|
+
m_msgFile = file_fopen(m_msgFileName.c_str(), "w+");
|
123
|
+
}
|
124
|
+
if (!m_msgFile) {
|
125
|
+
throw ConfigError("Could not open body file: " + m_msgFileName + " " + error_strerror());
|
126
|
+
}
|
127
|
+
|
128
|
+
m_headerFile = file_fopen(m_headerFileName.c_str(), "r+");
|
129
|
+
if (!m_headerFile) {
|
130
|
+
m_headerFile = file_fopen(m_headerFileName.c_str(), "w+");
|
131
|
+
}
|
132
|
+
if (!m_headerFile) {
|
133
|
+
throw ConfigError("Could not open header file: " + m_headerFileName + " " + error_strerror());
|
134
|
+
}
|
135
|
+
|
136
|
+
m_seqNumsFile = file_fopen(m_seqNumsFileName.c_str(), "r+");
|
137
|
+
if (!m_seqNumsFile) {
|
138
|
+
m_seqNumsFile = file_fopen(m_seqNumsFileName.c_str(), "w+");
|
139
|
+
}
|
140
|
+
if (!m_seqNumsFile) {
|
141
|
+
throw ConfigError("Could not open seqnums file: " + m_seqNumsFileName + " " + error_strerror());
|
142
|
+
}
|
143
|
+
|
144
|
+
bool setCreationTime = false;
|
145
|
+
m_sessionFile = file_fopen(m_sessionFileName.c_str(), "r");
|
146
|
+
if (!m_sessionFile) {
|
147
|
+
setCreationTime = true;
|
148
|
+
} else {
|
149
|
+
fclose(m_sessionFile);
|
150
|
+
}
|
151
|
+
|
152
|
+
m_sessionFile = file_fopen(m_sessionFileName.c_str(), "r+");
|
153
|
+
if (!m_sessionFile) {
|
154
|
+
m_sessionFile = file_fopen(m_sessionFileName.c_str(), "w+");
|
155
|
+
}
|
156
|
+
if (!m_sessionFile) {
|
157
|
+
throw ConfigError("Could not open session file " + error_strerror());
|
158
|
+
}
|
159
|
+
if (setCreationTime) {
|
160
|
+
setSession();
|
161
|
+
}
|
162
|
+
|
163
|
+
setNextSenderMsgSeqNum(getNextSenderMsgSeqNum());
|
164
|
+
setNextTargetMsgSeqNum(getNextTargetMsgSeqNum());
|
165
|
+
}
|
166
|
+
|
167
|
+
void FileStore::populateCache() {
|
168
|
+
FILE *headerFile = file_fopen(m_headerFileName.c_str(), "r+");
|
169
|
+
if (headerFile) {
|
170
|
+
SEQNUM msgSeqNum;
|
171
|
+
long offset;
|
172
|
+
std::size_t size;
|
173
|
+
|
174
|
+
while (FILE_FSCANF(headerFile, "%" SCNu64 ",%ld,%zu ", &msgSeqNum, &offset, &size) == 3) {
|
175
|
+
std::pair<NumToOffset::iterator, bool> it
|
176
|
+
= m_offsets.insert(NumToOffset::value_type(msgSeqNum, std::make_pair(offset, size)));
|
177
|
+
|
178
|
+
if (it.second == false) {
|
179
|
+
it.first->second = std::make_pair(offset, size);
|
180
|
+
}
|
181
|
+
}
|
182
|
+
fclose(headerFile);
|
183
|
+
}
|
184
|
+
|
185
|
+
struct stat seqNumsFileStat;
|
186
|
+
FILE *seqNumsFile = file_fopen(m_seqNumsFileName.c_str(), "r+");
|
187
|
+
|
188
|
+
if (seqNumsFile && stat(m_seqNumsFileName.c_str(), &seqNumsFileStat) == 0) {
|
189
|
+
if (seqNumsFileStat.st_size == sizeOf64BitSeqNumFile) {
|
190
|
+
SEQNUM sender, target;
|
191
|
+
if (FILE_FSCANF(seqNumsFile, "%" SCNu64 " : %" SCNu64, &sender, &target) == 2) {
|
192
|
+
m_cache.setNextSenderMsgSeqNum(sender);
|
193
|
+
m_cache.setNextTargetMsgSeqNum(target);
|
194
|
+
}
|
195
|
+
} else // try old int seq num file format
|
196
|
+
{
|
197
|
+
int sender, target;
|
198
|
+
if (FILE_FSCANF(seqNumsFile, "%d : %d", &sender, &target) == 2) {
|
199
|
+
m_cache.setNextSenderMsgSeqNum(sender);
|
200
|
+
m_cache.setNextTargetMsgSeqNum(target);
|
201
|
+
}
|
202
|
+
}
|
203
|
+
fclose(seqNumsFile);
|
204
|
+
}
|
205
|
+
|
206
|
+
FILE *sessionFile = file_fopen(m_sessionFileName.c_str(), "r+");
|
207
|
+
if (sessionFile) {
|
208
|
+
char time[22];
|
209
|
+
#ifdef HAVE_FSCANF_S
|
210
|
+
int result = FILE_FSCANF(sessionFile, "%s", time, 22);
|
211
|
+
#else
|
212
|
+
int result = FILE_FSCANF(sessionFile, "%s", time);
|
213
|
+
#endif
|
214
|
+
if (result == 1) {
|
215
|
+
m_cache.setCreationTime(UtcTimeStampConvertor::convert(time));
|
216
|
+
}
|
217
|
+
fclose(sessionFile);
|
218
|
+
}
|
219
|
+
}
|
220
|
+
|
221
|
+
MessageStore *FileStoreFactory::create(const UtcTimeStamp &now, const SessionID &sessionID) {
|
222
|
+
if (m_path.size()) {
|
223
|
+
return new FileStore(now, m_path, sessionID);
|
224
|
+
}
|
225
|
+
|
226
|
+
std::string path;
|
227
|
+
Dictionary settings = m_settings.get(sessionID);
|
228
|
+
path = settings.getString(FILE_STORE_PATH);
|
229
|
+
return new FileStore(now, path, sessionID);
|
230
|
+
}
|
231
|
+
|
232
|
+
void FileStoreFactory::destroy(MessageStore *pStore) { delete pStore; }
|
233
|
+
|
234
|
+
bool FileStore::set(SEQNUM msgSeqNum, const std::string &msg) EXCEPT(IOException) {
|
235
|
+
if (fseek(m_msgFile, 0, SEEK_END)) {
|
236
|
+
throw IOException("Cannot seek to end of " + m_msgFileName);
|
237
|
+
}
|
238
|
+
if (fseek(m_headerFile, 0, SEEK_END)) {
|
239
|
+
throw IOException("Cannot seek to end of " + m_headerFileName);
|
240
|
+
}
|
241
|
+
|
242
|
+
long offset = ftell(m_msgFile);
|
243
|
+
if (offset < 0) {
|
244
|
+
throw IOException("Unable to get file pointer position from " + m_msgFileName);
|
245
|
+
}
|
246
|
+
std::size_t size = msg.size();
|
247
|
+
|
248
|
+
if (fprintf(m_headerFile, "%" SCNu64 ",%ld,%zu ", msgSeqNum, offset, size) < 0) {
|
249
|
+
throw IOException("Unable to write to file " + m_headerFileName);
|
250
|
+
}
|
251
|
+
std::pair<NumToOffset::iterator, bool> it
|
252
|
+
= m_offsets.insert(NumToOffset::value_type(msgSeqNum, std::make_pair(offset, size)));
|
253
|
+
if (it.second == false) {
|
254
|
+
it.first->second = std::make_pair(offset, size);
|
255
|
+
}
|
256
|
+
fwrite(msg.c_str(), sizeof(char), msg.size(), m_msgFile);
|
257
|
+
if (ferror(m_msgFile)) {
|
258
|
+
throw IOException("Unable to write to file " + m_msgFileName);
|
259
|
+
}
|
260
|
+
if (fflush(m_msgFile) == EOF) {
|
261
|
+
throw IOException("Unable to flush file " + m_msgFileName);
|
262
|
+
}
|
263
|
+
if (fflush(m_headerFile) == EOF) {
|
264
|
+
throw IOException("Unable to flush file " + m_headerFileName);
|
265
|
+
}
|
266
|
+
return true;
|
267
|
+
}
|
268
|
+
|
269
|
+
void FileStore::get(SEQNUM begin, SEQNUM end, std::vector<std::string> &result) const EXCEPT(IOException) {
|
270
|
+
result.clear();
|
271
|
+
std::string msg;
|
272
|
+
for (auto i = begin; i <= end && i != 0; ++i) {
|
273
|
+
if (get(i, msg)) {
|
274
|
+
result.push_back(msg);
|
275
|
+
}
|
276
|
+
}
|
277
|
+
}
|
278
|
+
|
279
|
+
SEQNUM FileStore::getNextSenderMsgSeqNum() const EXCEPT(IOException) { return m_cache.getNextSenderMsgSeqNum(); }
|
280
|
+
|
281
|
+
SEQNUM FileStore::getNextTargetMsgSeqNum() const EXCEPT(IOException) { return m_cache.getNextTargetMsgSeqNum(); }
|
282
|
+
|
283
|
+
void FileStore::setNextSenderMsgSeqNum(SEQNUM value) EXCEPT(IOException) {
|
284
|
+
m_cache.setNextSenderMsgSeqNum(value);
|
285
|
+
setSeqNum();
|
286
|
+
}
|
287
|
+
|
288
|
+
void FileStore::setNextTargetMsgSeqNum(SEQNUM value) EXCEPT(IOException) {
|
289
|
+
m_cache.setNextTargetMsgSeqNum(value);
|
290
|
+
setSeqNum();
|
291
|
+
}
|
292
|
+
|
293
|
+
void FileStore::incrNextSenderMsgSeqNum() EXCEPT(IOException) {
|
294
|
+
m_cache.incrNextSenderMsgSeqNum();
|
295
|
+
setSeqNum();
|
296
|
+
}
|
297
|
+
|
298
|
+
void FileStore::incrNextTargetMsgSeqNum() EXCEPT(IOException) {
|
299
|
+
m_cache.incrNextTargetMsgSeqNum();
|
300
|
+
setSeqNum();
|
301
|
+
}
|
302
|
+
|
303
|
+
UtcTimeStamp FileStore::getCreationTime() const EXCEPT(IOException) { return m_cache.getCreationTime(); }
|
304
|
+
|
305
|
+
void FileStore::reset(const UtcTimeStamp &now) EXCEPT(IOException) {
|
306
|
+
try {
|
307
|
+
m_cache.reset(now);
|
308
|
+
m_offsets.clear();
|
309
|
+
open(true);
|
310
|
+
setSession();
|
311
|
+
} catch (std::exception &e) {
|
312
|
+
throw IOException(e.what());
|
313
|
+
}
|
314
|
+
}
|
315
|
+
|
316
|
+
void FileStore::refresh() EXCEPT(IOException) {
|
317
|
+
try {
|
318
|
+
m_cache.reset(UtcTimeStamp::now());
|
319
|
+
m_offsets.clear();
|
320
|
+
open(false);
|
321
|
+
} catch (std::exception &e) {
|
322
|
+
throw IOException(e.what());
|
323
|
+
}
|
324
|
+
}
|
325
|
+
|
326
|
+
void FileStore::setSeqNum() {
|
327
|
+
rewind(m_seqNumsFile);
|
328
|
+
fprintf(m_seqNumsFile, seqNumPairFileFormat.c_str(), getNextSenderMsgSeqNum(), getNextTargetMsgSeqNum());
|
329
|
+
if (ferror(m_seqNumsFile)) {
|
330
|
+
throw IOException("Unable to write to file " + m_seqNumsFileName);
|
331
|
+
}
|
332
|
+
if (fflush(m_seqNumsFile)) {
|
333
|
+
throw IOException("Unable to flush file " + m_seqNumsFileName);
|
334
|
+
}
|
335
|
+
}
|
336
|
+
|
337
|
+
void FileStore::setSession() {
|
338
|
+
rewind(m_sessionFile);
|
339
|
+
fprintf(m_sessionFile, "%s", UtcTimeStampConvertor::convert(m_cache.getCreationTime()).c_str());
|
340
|
+
if (ferror(m_sessionFile)) {
|
341
|
+
throw IOException("Unable to write to file " + m_sessionFileName);
|
342
|
+
}
|
343
|
+
if (fflush(m_sessionFile)) {
|
344
|
+
throw IOException("Unable to flush file " + m_sessionFileName);
|
345
|
+
}
|
346
|
+
}
|
347
|
+
|
348
|
+
bool FileStore::get(SEQNUM msgSeqNum, std::string &msg) const EXCEPT(IOException) {
|
349
|
+
NumToOffset::const_iterator find = m_offsets.find(msgSeqNum);
|
350
|
+
if (find == m_offsets.end()) {
|
351
|
+
return false;
|
352
|
+
}
|
353
|
+
const OffsetSize &offset = find->second;
|
354
|
+
if (fseek(m_msgFile, offset.first, SEEK_SET)) {
|
355
|
+
throw IOException("Unable to seek in file " + m_msgFileName);
|
356
|
+
}
|
357
|
+
char *buffer = new char[offset.second + 1];
|
358
|
+
size_t result = fread(buffer, sizeof(char), offset.second, m_msgFile);
|
359
|
+
if (ferror(m_msgFile) || result != (size_t)offset.second) {
|
360
|
+
delete[] buffer;
|
361
|
+
throw IOException("Unable to read from file " + m_msgFileName);
|
362
|
+
}
|
363
|
+
buffer[offset.second] = 0;
|
364
|
+
msg = buffer;
|
365
|
+
delete[] buffer;
|
366
|
+
return true;
|
367
|
+
}
|
368
|
+
|
369
|
+
} // namespace FIX
|