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 #ifdef HAVE_POSTGRESQL
27
28 #include "PostgreSQLLog.h"
29 #include "SessionID.h"
30 #include "SessionSettings.h"
31 #include "Utility.h"
32 #include "strptime.h"
33 #include <fstream>
34
35 namespace FIX
36 {
37
38 const std::string PostgreSQLLogFactory::DEFAULT_DATABASE = "quickfix";
39 const std::string PostgreSQLLogFactory::DEFAULT_USER = "postgres";
40 const std::string PostgreSQLLogFactory::DEFAULT_PASSWORD = "";
41 const std::string PostgreSQLLogFactory::DEFAULT_HOST = "localhost";
42 const short PostgreSQLLogFactory::DEFAULT_PORT = 0;
43
PostgreSQLLog(const SessionID & s,const DatabaseConnectionID & d,PostgreSQLConnectionPool * p)44 PostgreSQLLog::PostgreSQLLog
45 ( const SessionID& s, const DatabaseConnectionID& d, PostgreSQLConnectionPool* p )
46 : m_pConnectionPool( p )
47 {
48 init();
49 m_pSessionID = new SessionID( s );
50 m_pConnection = m_pConnectionPool->create( d );
51 }
52
PostgreSQLLog(const DatabaseConnectionID & d,PostgreSQLConnectionPool * p)53 PostgreSQLLog::PostgreSQLLog
54 ( const DatabaseConnectionID& d, PostgreSQLConnectionPool* p )
55 : m_pConnectionPool( p ), m_pSessionID( 0 )
56 {
57 init();
58 m_pConnection = m_pConnectionPool->create( d );
59 }
60
PostgreSQLLog(const SessionID & s,const std::string & database,const std::string & user,const std::string & password,const std::string & host,short port)61 PostgreSQLLog::PostgreSQLLog
62 ( const SessionID& s, const std::string& database, const std::string& user,
63 const std::string& password, const std::string& host, short port )
64 : m_pConnectionPool( 0 )
65 {
66 init();
67 m_pSessionID = new SessionID( s );
68 m_pConnection = new PostgreSQLConnection( database, user, password, host, port );
69 }
70
PostgreSQLLog(const std::string & database,const std::string & user,const std::string & password,const std::string & host,short port)71 PostgreSQLLog::PostgreSQLLog
72 ( const std::string& database, const std::string& user,
73 const std::string& password, const std::string& host, short port )
74 : m_pConnectionPool( 0 ), m_pSessionID( 0 )
75 {
76 init();
77 m_pConnection = new PostgreSQLConnection( database, user, password, host, port );
78 }
79
init()80 void PostgreSQLLog::init()
81 {
82 setIncomingTable( "messages_log" );
83 setOutgoingTable( "messages_log" );
84 setEventTable( "event_log" );
85 }
86
~PostgreSQLLog()87 PostgreSQLLog::~PostgreSQLLog()
88 {
89 if( m_pConnectionPool )
90 m_pConnectionPool->destroy( m_pConnection );
91 else
92 delete m_pConnection;
93 delete m_pSessionID;
94 }
95
create()96 Log* PostgreSQLLogFactory::create()
97 {
98 std::string database;
99 std::string user;
100 std::string password;
101 std::string host;
102 short port;
103
104 init( m_settings.get(), database, user, password, host, port );
105 DatabaseConnectionID id( database, user, password, host, port );
106 PostgreSQLLog* result = new PostgreSQLLog( id, m_connectionPoolPtr.get() );
107 initLog( m_settings.get(), *result );
108 return result;
109 }
110
create(const SessionID & s)111 Log* PostgreSQLLogFactory::create( const SessionID& s )
112 {
113 std::string database;
114 std::string user;
115 std::string password;
116 std::string host;
117 short port;
118
119 Dictionary settings;
120 if( m_settings.has(s) )
121 settings = m_settings.get( s );
122
123 init( settings, database, user, password, host, port );
124 DatabaseConnectionID id( database, user, password, host, port );
125 PostgreSQLLog* result = new PostgreSQLLog( s, id, m_connectionPoolPtr.get() );
126 initLog( settings, *result );
127 return result;
128 }
129
init(const Dictionary & settings,std::string & database,std::string & user,std::string & password,std::string & host,short & port)130 void PostgreSQLLogFactory::init( const Dictionary& settings,
131 std::string& database,
132 std::string& user,
133 std::string& password,
134 std::string& host,
135 short &port )
136 {
137 database = DEFAULT_DATABASE;
138 user = DEFAULT_USER;
139 password = DEFAULT_PASSWORD;
140 host = DEFAULT_HOST;
141 port = DEFAULT_PORT;
142
143 if( m_useSettings )
144 {
145 try { database = settings.getString( POSTGRESQL_LOG_DATABASE ); }
146 catch( ConfigError& ) {}
147
148 try { user = settings.getString( POSTGRESQL_LOG_USER ); }
149 catch( ConfigError& ) {}
150
151 try { password = settings.getString( POSTGRESQL_LOG_PASSWORD ); }
152 catch( ConfigError& ) {}
153
154 try { host = settings.getString( POSTGRESQL_LOG_HOST ); }
155 catch( ConfigError& ) {}
156
157 try { port = ( short ) settings.getInt( POSTGRESQL_LOG_PORT ); }
158 catch( ConfigError& ) {}
159 }
160 else
161 {
162 database = m_database;
163 user = m_user;
164 password = m_password;
165 host = m_host;
166 port = m_port;
167 }
168 }
169
initLog(const Dictionary & settings,PostgreSQLLog & log)170 void PostgreSQLLogFactory::initLog( const Dictionary& settings, PostgreSQLLog& log )
171 {
172 try { log.setIncomingTable( settings.getString( POSTGRESQL_LOG_INCOMING_TABLE ) ); }
173 catch( ConfigError& ) {}
174
175 try { log.setOutgoingTable( settings.getString( POSTGRESQL_LOG_OUTGOING_TABLE ) ); }
176 catch( ConfigError& ) {}
177
178 try { log.setEventTable( settings.getString( POSTGRESQL_LOG_EVENT_TABLE ) ); }
179 catch( ConfigError& ) {}
180 }
181
destroy(Log * pLog)182 void PostgreSQLLogFactory::destroy( Log* pLog )
183 {
184 delete pLog;
185 }
186
clear()187 void PostgreSQLLog::clear()
188 {
189 std::stringstream whereClause;
190
191 whereClause << "WHERE ";
192
193 if( m_pSessionID )
194 {
195 whereClause
196 << "BeginString = '" << m_pSessionID->getBeginString().getValue() << "' "
197 << "AND SenderCompID = '" << m_pSessionID->getSenderCompID().getValue() << "' "
198 << "AND TargetCompID = '" << m_pSessionID->getTargetCompID().getValue() << "' ";
199
200 if( m_pSessionID->getSessionQualifier().size() )
201 whereClause << "AND SessionQualifier = '" << m_pSessionID->getSessionQualifier() << "'";
202 }
203 else
204 {
205 whereClause << "BeginString = NULL AND SenderCompID = NULL && TargetCompID = NULL";
206 }
207
208 std::stringstream incomingQuery;
209 std::stringstream outgoingQuery;
210 std::stringstream eventQuery;
211
212 incomingQuery
213 << "DELETE FROM " << m_incomingTable << " " << whereClause.str();
214 outgoingQuery
215 << "DELETE FROM " << m_outgoingTable << " " << whereClause.str();
216 eventQuery
217 << "DELETE FROM " << m_eventTable << " " << whereClause.str();
218
219 PostgreSQLQuery incoming( incomingQuery.str() );
220 PostgreSQLQuery outgoing( outgoingQuery.str() );
221 PostgreSQLQuery event( eventQuery.str() );
222 m_pConnection->execute( incoming );
223 m_pConnection->execute( outgoing );
224 m_pConnection->execute( event );
225 }
226
backup()227 void PostgreSQLLog::backup()
228 {
229 }
230
insert(const std::string & table,const std::string value)231 void PostgreSQLLog::insert( const std::string& table, const std::string value )
232 {
233 UtcTimeStamp time;
234 int year, month, day, hour, minute, second, millis;
235 time.getYMD( year, month, day );
236 time.getHMS( hour, minute, second, millis );
237
238 char sqlTime[ 24 ];
239 STRING_SPRINTF( sqlTime, "%d-%02d-%02d %02d:%02d:%02d.%003d",
240 year, month, day, hour, minute, second, millis );
241
242 char* valueCopy = new char[ (value.size() * 2) + 1 ];
243 PQescapeString( valueCopy, value.c_str(), value.size() );
244
245 std::stringstream queryString;
246 queryString << "INSERT INTO " << table << " "
247 << "(time, beginstring, sendercompid, targetcompid, session_qualifier, text) "
248 << "VALUES ("
249 << "'" << sqlTime << "',";
250
251 if( m_pSessionID )
252 {
253 queryString
254 << "'" << m_pSessionID->getBeginString().getValue() << "',"
255 << "'" << m_pSessionID->getSenderCompID().getValue() << "',"
256 << "'" << m_pSessionID->getTargetCompID().getValue() << "',";
257 if( m_pSessionID->getSessionQualifier() == "" )
258 queryString << "NULL" << ",";
259 else
260 queryString << "'" << m_pSessionID->getSessionQualifier() << "',";
261 }
262 else
263 {
264 queryString << "NULL, NULL, NULL, NULL, ";
265 }
266
267 queryString << "'" << valueCopy << "')";
268 delete [] valueCopy;
269
270 PostgreSQLQuery query( queryString.str() );
271 m_pConnection->execute( query );
272 }
273
274 } // namespace FIX
275
276 #endif //HAVE_POSTGRESQL
277