SessionFactory.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 "Utility.h"
27 #include "Values.h"
28 #include "DataDictionaryProvider.h"
29 #include "SessionFactory.h"
30 #include "SessionSettings.h"
31 #include "Session.h"
32 
33 #include <memory>
34 
35 namespace FIX
36 {
38 {
39 }
40 
42  const Dictionary& settings ) throw( ConfigError )
43 {
44  std::string connectionType = settings.getString( CONNECTION_TYPE );
45  if ( connectionType != "acceptor" && connectionType != "initiator" )
46  throw ConfigError( "Invalid ConnectionType" );
47 
48  if( connectionType == "acceptor" && settings.has(SESSION_QUALIFIER) )
49  throw ConfigError( "SessionQualifier cannot be used with acceptor." );
50 
51  bool useDataDictionary = true;
52  if ( settings.has( USE_DATA_DICTIONARY ) )
53  useDataDictionary = settings.getBool( USE_DATA_DICTIONARY );
54 
55  std::string defaultApplVerID;
56  if( sessionID.isFIXT() )
57  {
58  if( !settings.has(DEFAULT_APPLVERID) )
59  {
60  throw ConfigError("ApplVerID is required for FIXT transport");
61  }
62  defaultApplVerID = Message::toApplVerID( settings.getString(DEFAULT_APPLVERID) );
63  }
64 
65  DataDictionaryProvider dataDictionaryProvider;
66  if( useDataDictionary )
67  {
68  if( sessionID.isFIXT() )
69  {
70  processFixtDataDictionaries(sessionID, settings, dataDictionaryProvider);
71  }
72  else
73  {
74  processFixDataDictionary(sessionID, settings, dataDictionaryProvider);
75  }
76  }
77 
78  bool useLocalTime = false;
79  if( settings.has(USE_LOCAL_TIME) )
80  useLocalTime = settings.getBool( USE_LOCAL_TIME );
81 
82  int startDay = -1;
83  int endDay = -1;
84  try
85  {
86  startDay = settings.getDay( START_DAY );
87  endDay = settings.getDay( END_DAY );
88  }
89  catch( ConfigError & ) {}
90  catch( FieldConvertError & e ) { throw ConfigError( e.what() ); }
91 
92  UtcTimeOnly startTime;
93  UtcTimeOnly endTime;
94  try
95  {
97  ( settings.getString( START_TIME ) );
99  ( settings.getString( END_TIME ) );
100  }
101  catch ( FieldConvertError & e ) { throw ConfigError( e.what() ); }
102 
103  TimeRange utcSessionTime
104  ( startTime, endTime, startDay, endDay );
105  TimeRange localSessionTime
106  ( LocalTimeOnly(startTime.getHour(), startTime.getMinute(), startTime.getSecond()),
107  LocalTimeOnly(endTime.getHour(), endTime.getMinute(), endTime.getSecond()),
108  startDay, endDay );
109  TimeRange sessionTimeRange = useLocalTime ? localSessionTime : utcSessionTime;
110 
111  if( startDay >= 0 && endDay < 0 )
112  throw ConfigError( "StartDay used without EndDay" );
113  if( endDay >= 0 && startDay < 0 )
114  throw ConfigError( "EndDay used without StartDay" );
115 
116  HeartBtInt heartBtInt( 0 );
117  if ( connectionType == "initiator" )
118  {
119  heartBtInt = HeartBtInt( settings.getInt( HEARTBTINT ) );
120  if ( heartBtInt <= 0 ) throw ConfigError( "Heartbeat must be greater than zero" );
121  }
122 
123  std::auto_ptr<Session> pSession;
124  pSession.reset( new Session( m_application, m_messageStoreFactory,
125  sessionID, dataDictionaryProvider, sessionTimeRange,
126  heartBtInt, m_pLogFactory ) );
127 
128  pSession->setSenderDefaultApplVerID(defaultApplVerID);
129 
130  int logonDay = startDay;
131  int logoutDay = endDay;
132  try
133  {
134  logonDay = settings.getDay( LOGON_DAY );
135  logoutDay = settings.getDay( LOGOUT_DAY );
136  }
137  catch( ConfigError & ) {}
138  catch( FieldConvertError & e ) { throw ConfigError( e.what() ); }
139 
140  UtcTimeOnly logonTime( startTime );
141  UtcTimeOnly logoutTime( endTime );
142  try
143  {
145  ( settings.getString( LOGON_TIME ) );
146  }
147  catch( ConfigError & ) {}
148  catch( FieldConvertError & e ) { throw ConfigError( e.what() ); }
149  try
150  {
151  logoutTime = UtcTimeOnlyConvertor::convert
152  ( settings.getString( LOGOUT_TIME ) );
153  }
154  catch( ConfigError & ) {}
155  catch( FieldConvertError & e ) { throw ConfigError( e.what() ); }
156 
157  TimeRange utcLogonTime
158  ( logonTime, logoutTime, logonDay, logoutDay );
159  TimeRange localLogonTime
160  ( LocalTimeOnly(logonTime.getHour(), logonTime.getMinute(), logonTime.getSecond()),
161  LocalTimeOnly(logoutTime.getHour(), logoutTime.getMinute(), logoutTime.getSecond()),
162  logonDay, logoutDay );
163  TimeRange logonTimeRange = useLocalTime ? localLogonTime : utcLogonTime;
164 
165  if( !sessionTimeRange.isInRange(logonTime, logonDay) )
166  throw ConfigError( "LogonTime must be between StartTime and EndTime" );
167  if( !sessionTimeRange.isInRange(logoutTime, logoutDay) )
168  throw ConfigError( "LogoutTime must be between StartTime and EndTime" );
169  pSession->setLogonTime( logonTimeRange );
170 
171  if ( settings.has( SEND_REDUNDANT_RESENDREQUESTS ) )
172  pSession->setSendRedundantResendRequests( settings.getBool( SEND_REDUNDANT_RESENDREQUESTS ) );
173  if ( settings.has( CHECK_COMPID ) )
174  pSession->setCheckCompId( settings.getBool( CHECK_COMPID ) );
175  if ( settings.has( CHECK_LATENCY ) )
176  pSession->setCheckLatency( settings.getBool( CHECK_LATENCY ) );
177  if ( settings.has( MAX_LATENCY ) )
178  pSession->setMaxLatency( settings.getInt( MAX_LATENCY ) );
179  if ( settings.has( LOGON_TIMEOUT ) )
180  pSession->setLogonTimeout( settings.getInt( LOGON_TIMEOUT ) );
181  if ( settings.has( LOGOUT_TIMEOUT ) )
182  pSession->setLogoutTimeout( settings.getInt( LOGOUT_TIMEOUT ) );
183  if ( settings.has( RESET_ON_LOGON ) )
184  pSession->setResetOnLogon( settings.getBool( RESET_ON_LOGON ) );
185  if ( settings.has( RESET_ON_LOGOUT ) )
186  pSession->setResetOnLogout( settings.getBool( RESET_ON_LOGOUT ) );
187  if ( settings.has( RESET_ON_DISCONNECT ) )
188  pSession->setResetOnDisconnect( settings.getBool( RESET_ON_DISCONNECT ) );
189  if ( settings.has( REFRESH_ON_LOGON ) )
190  pSession->setRefreshOnLogon( settings.getBool( REFRESH_ON_LOGON ) );
191  if ( settings.has( MILLISECONDS_IN_TIMESTAMP ) )
192  pSession->setMillisecondsInTimeStamp( settings.getBool( MILLISECONDS_IN_TIMESTAMP ) );
193  if ( settings.has( PERSIST_MESSAGES ) )
194  pSession->setPersistMessages( settings.getBool( PERSIST_MESSAGES ) );
195  if ( settings.has( VALIDATE_LENGTH_AND_CHECKSUM ) )
196  pSession->setValidateLengthAndChecksum( settings.getBool( VALIDATE_LENGTH_AND_CHECKSUM ) );
197 
198  return pSession.release();
199 }
200 
202 {
203  delete pSession;
204 }
205 
206 ptr::shared_ptr<DataDictionary> SessionFactory::createDataDictionary(const SessionID& sessionID,
207  const Dictionary& settings,
208  const std::string& settingsKey) throw(ConfigError)
209 {
210  ptr::shared_ptr<DataDictionary> pDD;
211  std::string path = settings.getString( settingsKey );
212  Dictionaries::iterator i = m_dictionaries.find( path );
213  if ( i != m_dictionaries.end() )
214  {
215  pDD = i->second;
216  }
217  else
218  {
219  pDD = ptr::shared_ptr<DataDictionary>(new DataDictionary( path ));
220  m_dictionaries[ path ] = pDD;
221  }
222 
223  ptr::shared_ptr<DataDictionary> pCopyOfDD = ptr::shared_ptr<DataDictionary>(new DataDictionary(*pDD));
224 
225  if( settings.has( VALIDATE_FIELDS_OUT_OF_ORDER ) )
226  pCopyOfDD->checkFieldsOutOfOrder( settings.getBool( VALIDATE_FIELDS_OUT_OF_ORDER ) );
227  if( settings.has( VALIDATE_FIELDS_HAVE_VALUES ) )
228  pCopyOfDD->checkFieldsHaveValues( settings.getBool( VALIDATE_FIELDS_HAVE_VALUES ) );
229  if( settings.has( VALIDATE_USER_DEFINED_FIELDS ) )
230  pCopyOfDD->checkUserDefinedFields( settings.getBool( VALIDATE_USER_DEFINED_FIELDS ) );
231 
232  return pCopyOfDD;
233 }
234 
236  const Dictionary& settings,
237  DataDictionaryProvider& provider) throw(ConfigError)
238 {
239  ptr::shared_ptr<DataDictionary> pDataDictionary = createDataDictionary(sessionID, settings, TRANSPORT_DATA_DICTIONARY);
240  provider.addTransportDataDictionary(sessionID.getBeginString(), pDataDictionary);
241 
242  for(Dictionary::const_iterator data = settings.begin(); data != settings.end(); ++data)
243  {
244  const std::string& key = data->first;
245  const std::string frontKey = key.substr(0, strlen(APP_DATA_DICTIONARY));
246  if( frontKey == string_toUpper(APP_DATA_DICTIONARY) )
247  {
248  if( key == string_toUpper(APP_DATA_DICTIONARY) )
249  {
250  provider.addApplicationDataDictionary(Message::toApplVerID(settings.getString(DEFAULT_APPLVERID)),
251  createDataDictionary(sessionID, settings, APP_DATA_DICTIONARY));
252  }
253  else
254  {
255  std::string::size_type offset = key.find('.');
256  if( offset == std::string::npos )
257  throw ConfigError(std::string("Malformed ") + APP_DATA_DICTIONARY + ": " + key);
258  std::string beginStringQualifier = key.substr(offset+1);
259  provider.addApplicationDataDictionary(Message::toApplVerID(beginStringQualifier),
260  createDataDictionary(sessionID, settings, key));
261  }
262  }
263  }
264 }
265 
267  const Dictionary& settings,
268  DataDictionaryProvider& provider) throw(ConfigError)
269 {
270  ptr::shared_ptr<DataDictionary> pDataDictionary = createDataDictionary(sessionID, settings, DATA_DICTIONARY);
271  provider.addTransportDataDictionary(sessionID.getBeginString(), pDataDictionary);
272  provider.addApplicationDataDictionary(Message::toApplVerID(sessionID.getBeginString()), pDataDictionary);
273 }
274 }
const char LOGON_TIMEOUT[]
ptr::shared_ptr< DataDictionary > createDataDictionary(const SessionID &sessionID, const Dictionary &settings, const std::string &settingsKey)
Unable to convert field into its native format.
Definition: Exceptions.h:66
static std::string convert(const UtcTimeOnly &value, bool showMilliseconds=false)
const char RESET_ON_LOGON[]
const char RESET_ON_DISCONNECT[]
const char LOGOUT_DAY[]
LogFactory * m_pLogFactory
Keeps track of when session is active.
Definition: TimeRange.h:34
const int HeartBtInt
Time only represented in UTC.
Definition: FieldTypes.h:469
Represents a data dictionary for a version of FIX.
const char RESET_ON_LOGOUT[]
const char CONNECTION_TYPE[]
const char LOGOUT_TIME[]
const char VALIDATE_FIELDS_HAVE_VALUES[]
Maintains the state and implements the logic of a FIX session.
Definition: Session.h:45
const char MAX_LATENCY[]
const char DEFAULT_APPLVERID[]
Queries for DataDictionary based on appropriate version of FIX.
static ApplVerID toApplVerID(const BeginString &value)
Definition: Message.h:257
void processFixDataDictionary(const SessionID &sessionID, const Dictionary &settings, DataDictionaryProvider &provider)
const char SEND_REDUNDANT_RESENDREQUESTS[]
const char SESSION_QUALIFIER[]
const char VALIDATE_FIELDS_OUT_OF_ORDER[]
const char LOGON_TIME[]
MessageStoreFactory & m_messageStoreFactory
int getSecond() const
Return the second portion of the time (0-59)
Definition: FieldTypes.h:132
const char END_TIME[]
static bool isInRange(const UtcTimeOnly &start, const UtcTimeOnly &end, const DateTime &time)
Definition: TimeRange.h:43
int getMinute() const
Return the minute portion of the time (0-59)
Definition: FieldTypes.h:126
const char VALIDATE_USER_DEFINED_FIELDS[]
Time only represented in local time.
Definition: FieldTypes.h:510
void processFixtDataDictionaries(const SessionID &sessionID, const Dictionary &settings, DataDictionaryProvider &provider)
const char END_DAY[]
const char TRANSPORT_DATA_DICTIONARY[]
Definition: Acceptor.cpp:34
std::string string_toUpper(const std::string &value)
Definition: Utility.cpp:53
const char START_DAY[]
Application is not configured correctly
Definition: Exceptions.h:87
const char CHECK_COMPID[]
Application & m_application
const char VALIDATE_LENGTH_AND_CHECKSUM[]
const char LOGOUT_TIMEOUT[]
const char START_TIME[]
Dictionaries m_dictionaries
const char LOGON_DAY[]
const char MILLISECONDS_IN_TIMESTAMP[]
const char DATA_DICTIONARY[]
const char USE_DATA_DICTIONARY[]
Session * create(const SessionID &sessionID, const Dictionary &settings)
For storage and retrieval of key/value pairs.
Definition: Dictionary.h:36
int getHour() const
Return the hour portion of the time (0-23)
Definition: FieldTypes.h:120
iterator const_iterator
Definition: Dictionary.h:45
void destroy(Session *pSession)
const char USE_LOCAL_TIME[]
Unique session id consists of BeginString, SenderCompID and TargetCompID.
Definition: SessionID.h:30
const char PERSIST_MESSAGES[]
const char HEARTBTINT[]
const char CHECK_LATENCY[]
const char APP_DATA_DICTIONARY[]
const char REFRESH_ON_LOGON[]

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