00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifdef _MSC_VER
00021 #include "stdafx.h"
00022 #else
00023 #include "config.h"
00024 #endif
00025 #include "CallStack.h"
00026
00027 #ifdef HAVE_MYSQL
00028
00029 #include "MySQLLog.h"
00030 #include "SessionID.h"
00031 #include "SessionSettings.h"
00032 #include "Utility.h"
00033 #include "strptime.h"
00034 #include <fstream>
00035
00036 namespace FIX
00037 {
00038
00039 const std::string MySQLLogFactory::DEFAULT_DATABASE = "quickfix";
00040 const std::string MySQLLogFactory::DEFAULT_USER = "root";
00041 const std::string MySQLLogFactory::DEFAULT_PASSWORD = "";
00042 const std::string MySQLLogFactory::DEFAULT_HOST = "localhost";
00043 const short MySQLLogFactory::DEFAULT_PORT = 0;
00044
00045 MySQLLog::MySQLLog
00046 ( const SessionID& s, const DatabaseConnectionID& d, MySQLConnectionPool* p )
00047 : m_pConnectionPool( p )
00048 {
00049 init();
00050 m_pSessionID = new SessionID( s );
00051 m_pConnection = m_pConnectionPool->create( d );
00052 }
00053
00054 MySQLLog::MySQLLog
00055 ( const DatabaseConnectionID& d, MySQLConnectionPool* p )
00056 : m_pConnectionPool( p ), m_pSessionID( 0 )
00057 {
00058 init();
00059 m_pConnection = m_pConnectionPool->create( d );
00060 }
00061
00062 MySQLLog::MySQLLog
00063 ( const SessionID& s, const std::string& database, const std::string& user,
00064 const std::string& password, const std::string& host, short port )
00065 : m_pConnectionPool( 0 )
00066 {
00067 init();
00068 m_pSessionID = new SessionID( s );
00069 m_pConnection = new MySQLConnection( database, user, password, host, port );
00070 }
00071
00072 MySQLLog::MySQLLog
00073 ( const std::string& database, const std::string& user,
00074 const std::string& password, const std::string& host, short port )
00075 : m_pConnectionPool( 0 ), m_pSessionID( 0 )
00076 {
00077 m_pConnection = new MySQLConnection( database, user, password, host, port );
00078 }
00079
00080 void MySQLLog::init()
00081 {
00082 setIncomingTable( "messages_log" );
00083 setOutgoingTable( "messages_log" );
00084 setEventTable( "event_log" );
00085 }
00086
00087 MySQLLog::~MySQLLog()
00088 {
00089 if( m_pConnectionPool )
00090 m_pConnectionPool->destroy( m_pConnection );
00091 else
00092 delete m_pConnection;
00093 delete m_pSessionID;
00094 }
00095
00096 Log* MySQLLogFactory::create()
00097 { QF_STACK_PUSH(MySQLLogFactory::create)
00098
00099 std::string database;
00100 std::string user;
00101 std::string password;
00102 std::string host;
00103 short port;
00104
00105 init( m_settings.get(), database, user, password, host, port );
00106 DatabaseConnectionID id( database, user, password, host, port );
00107 MySQLLog* result = new MySQLLog( id, m_connectionPoolPtr.get() );
00108 initLog( m_settings.get(), *result );
00109 return result;
00110
00111 QF_STACK_POP
00112 }
00113
00114 Log* MySQLLogFactory::create( const SessionID& s )
00115 { QF_STACK_PUSH(MySQLLogFactory::create)
00116
00117 std::string database;
00118 std::string user;
00119 std::string password;
00120 std::string host;
00121 short port;
00122
00123 Dictionary settings;
00124 if( m_settings.has(s) )
00125 settings = m_settings.get( s );
00126
00127 init( settings, database, user, password, host, port );
00128 DatabaseConnectionID id( database, user, password, host, port );
00129 MySQLLog* result = new MySQLLog( s, id, m_connectionPoolPtr.get() );
00130 initLog( settings, *result );
00131 return result;
00132
00133 QF_STACK_POP
00134 }
00135
00136 void MySQLLogFactory::init( const Dictionary& settings,
00137 std::string& database,
00138 std::string& user,
00139 std::string& password,
00140 std::string& host,
00141 short &port )
00142 { QF_STACK_PUSH(MySQLLogFactory::init)
00143
00144 database = DEFAULT_DATABASE;
00145 user = DEFAULT_USER;
00146 password = DEFAULT_PASSWORD;
00147 host = DEFAULT_HOST;
00148 port = DEFAULT_PORT;
00149
00150 if( m_useSettings )
00151 {
00152 try { database = settings.getString( MYSQL_LOG_DATABASE ); }
00153 catch( ConfigError& ) {}
00154
00155 try { user = settings.getString( MYSQL_LOG_USER ); }
00156 catch( ConfigError& ) {}
00157
00158 try { password = settings.getString( MYSQL_LOG_PASSWORD ); }
00159 catch( ConfigError& ) {}
00160
00161 try { host = settings.getString( MYSQL_LOG_HOST ); }
00162 catch( ConfigError& ) {}
00163
00164 try { port = ( short ) settings.getLong( MYSQL_LOG_PORT ); }
00165 catch( ConfigError& ) {}
00166 }
00167 else
00168 {
00169 database = m_database;
00170 user = m_user;
00171 password = m_password;
00172 host = m_host;
00173 port = m_port;
00174 }
00175
00176 QF_STACK_POP
00177 }
00178
00179 void MySQLLogFactory::initLog( const Dictionary& settings, MySQLLog& log )
00180 {
00181 try { log.setIncomingTable( settings.getString( MYSQL_LOG_INCOMING_TABLE ) ); }
00182 catch( ConfigError& ) {}
00183
00184 try { log.setOutgoingTable( settings.getString( MYSQL_LOG_OUTGOING_TABLE ) ); }
00185 catch( ConfigError& ) {}
00186
00187 try { log.setEventTable( settings.getString( MYSQL_LOG_EVENT_TABLE ) ); }
00188 catch( ConfigError& ) {}
00189 }
00190
00191 void MySQLLogFactory::destroy( Log* pLog )
00192 { QF_STACK_PUSH(MySQLLogFactory::destroy)
00193 delete pLog;
00194 QF_STACK_POP
00195 }
00196
00197 void MySQLLog::clear()
00198 { QF_STACK_PUSH(MySQLLog::clear)
00199
00200 std::stringstream whereClause;
00201
00202 whereClause << "WHERE ";
00203
00204 if( m_pSessionID )
00205 {
00206 whereClause
00207 << "BeginString = \"" << m_pSessionID->getBeginString().getValue() << "\" "
00208 << "AND SenderCompID = \"" << m_pSessionID->getSenderCompID().getValue() << "\" "
00209 << "AND TargetCompID = \"" << m_pSessionID->getTargetCompID().getValue() << "\" ";
00210
00211 if( m_pSessionID->getSessionQualifier().size() )
00212 whereClause << "AND SessionQualifier = \"" << m_pSessionID->getSessionQualifier() << "\"";
00213 }
00214 else
00215 {
00216 whereClause << "BeginString = NULL AND SenderCompID = NULL && TargetCompID = NULL";
00217 }
00218
00219 std::stringstream incomingQuery;
00220 std::stringstream outgoingQuery;
00221 std::stringstream eventQuery;
00222
00223 incomingQuery
00224 << "DELETE FROM " << m_incomingTable << " " << whereClause.str();
00225 outgoingQuery
00226 << "DELETE FROM " << m_outgoingTable << " " << whereClause.str();
00227 eventQuery
00228 << "DELETE FROM " << m_eventTable << " " << whereClause.str();
00229
00230 MySQLQuery incoming( incomingQuery.str() );
00231 MySQLQuery outgoing( outgoingQuery.str() );
00232 MySQLQuery event( eventQuery.str() );
00233 m_pConnection->execute( incoming );
00234 m_pConnection->execute( outgoing );
00235 m_pConnection->execute( event );
00236
00237 QF_STACK_POP
00238 }
00239
00240 void MySQLLog::backup()
00241 { QF_STACK_PUSH(MySQLLog::backup)
00242 QF_STACK_POP
00243 }
00244
00245 void MySQLLog::insert( const std::string& table, const std::string value )
00246 { QF_STACK_PUSH(MySQLLog::insert)
00247
00248 UtcTimeStamp time;
00249 int year, month, day, hour, minute, second, millis;
00250 time.getYMD( year, month, day );
00251 time.getHMS( hour, minute, second, millis );
00252
00253 char sqlTime[ 20 ];
00254 STRING_SPRINTF( sqlTime, "%d-%02d-%02d %02d:%02d:%02d",
00255 year, month, day, hour, minute, second );
00256
00257 char* valueCopy = new char[ (value.size() * 2) + 1 ];
00258 mysql_escape_string( valueCopy, value.c_str(), value.size() );
00259
00260 std::stringstream queryString;
00261 queryString << "INSERT INTO " << table << " "
00262 << "(time, time_milliseconds, beginstring, sendercompid, targetcompid, session_qualifier, text) "
00263 << "VALUES ("
00264 << "'" << sqlTime << "','" << millis << "',";
00265
00266 if( m_pSessionID )
00267 {
00268 queryString
00269 << "\"" << m_pSessionID->getBeginString().getValue() << "\","
00270 << "\"" << m_pSessionID->getSenderCompID().getValue() << "\","
00271 << "\"" << m_pSessionID->getTargetCompID().getValue() << "\",";
00272 if( m_pSessionID->getSessionQualifier() == "" )
00273 queryString << "NULL" << ",";
00274 else
00275 queryString << "\"" << m_pSessionID->getSessionQualifier() << "\",";
00276 }
00277 else
00278 {
00279 queryString << "NULL, NULL, NULL, NULL, ";
00280 }
00281
00282 queryString << "\"" << valueCopy << "\")";
00283 delete [] valueCopy;
00284
00285 MySQLQuery query( queryString.str() );
00286 m_pConnection->execute( query );
00287
00288 QF_STACK_POP
00289 }
00290
00291 }
00292
00293 #endif //HAVE_MYSQL