Index: core/src/main/java/quickfix/SessionSchedule.java =================================================================== --- core/src/main/java/quickfix/SessionSchedule.java (revision 621) +++ core/src/main/java/quickfix/SessionSchedule.java (working copy) @@ -28,14 +28,14 @@ /** * Corresponds to SessionTime in C++ code */ -class SessionSchedule { +public class SessionSchedule { private static final int NOT_SET = -1; private static final Pattern TIME_PATTERN = Pattern.compile("(\\d{2}):(\\d{2}):(\\d{2})"); private final TimeEndPoint startTime; private final TimeEndPoint endTime; private final TimeZone sessionTimeZone; - SessionSchedule(SessionSettings settings, SessionID sessionID) throws ConfigError, + public SessionSchedule(SessionSettings settings, SessionID sessionID) throws ConfigError, FieldConvertError { boolean startDayPresent = settings.isSetting(sessionID, Session.SETTING_START_DAY); boolean endDayPresent = settings.isSetting(sessionID, Session.SETTING_END_DAY); Index: core/src/main/java/quickfix/mina/acceptor/AcceptorIoHandler.java =================================================================== --- core/src/main/java/quickfix/mina/acceptor/AcceptorIoHandler.java (revision 621) +++ core/src/main/java/quickfix/mina/acceptor/AcceptorIoHandler.java (working copy) @@ -41,11 +41,19 @@ private final EventHandlingStrategy eventHandlingStrategy; + private final boolean useDynamicSessions; + public AcceptorIoHandler(Map acceptorSessions, NetworkingOptions networkingOptions, EventHandlingStrategy eventHandingStrategy) { + this(acceptorSessions, networkingOptions, eventHandingStrategy, false); + } + + public AcceptorIoHandler(Map acceptorSessions, NetworkingOptions networkingOptions, + EventHandlingStrategy eventHandingStrategy, boolean useDynamicSessions) { super(networkingOptions); this.acceptorSessions = acceptorSessions; this.eventHandlingStrategy = eventHandingStrategy; + this.useDynamicSessions = useDynamicSessions; } public void sessionCreated(IoSession session) throws Exception { @@ -59,6 +67,9 @@ if (qfSession == null) { if (message.getHeader().getString(MsgType.FIELD).equals(MsgType.LOGON)) { qfSession = (Session) acceptorSessions.get(sessionID); + if (qfSession == null && useDynamicSessions){ + qfSession = Session.lookupSession(sessionID); + } if (qfSession != null) { Log sessionLog = qfSession.getLog(); if (qfSession.hasResponder()) { Index: core/src/main/java/quickfix/mina/acceptor/AbstractSocketAcceptor.java =================================================================== --- core/src/main/java/quickfix/mina/acceptor/AbstractSocketAcceptor.java (revision 621) +++ core/src/main/java/quickfix/mina/acceptor/AbstractSocketAcceptor.java (working copy) @@ -66,12 +66,16 @@ private final SessionFactory sessionFactory; private final Map socketDescriptorForAddress = new HashMap(); private final Map ioAcceptorForTransport = new HashMap(); + private boolean useDynamicSessions = false; protected AbstractSocketAcceptor(SessionSettings settings, SessionFactory sessionFactory) throws ConfigError { super(settings, sessionFactory); this.sessionFactory = sessionFactory; try { + if (settings.isSetting(SETTING_USE_DYNAMIC_SESSIONS)) { + useDynamicSessions = settings.getBool(SETTING_USE_DYNAMIC_SESSIONS); + } createSessions(settings); } catch (FieldConvertError e) { throw new ConfigError(e); @@ -119,7 +123,7 @@ serviceConfig.setThreadModel(ThreadModel.MANUAL); ioAcceptor.bind(socketDescriptor.getAddress(), new AcceptorIoHandler( socketDescriptor.getAcceptedSessions(), new NetworkingOptions(settings - .getDefaultProperties()), eventHandlingStrategy)); + .getDefaultProperties()), eventHandlingStrategy, useDynamicSessions)); log.info("Listening for connections at " + socketDescriptor.getAddress()); } } catch (FieldConvertError e) { @@ -236,8 +240,14 @@ } setSessions(allSessions); - if (socketDescriptorForAddress.size() == 0) { - throw new ConfigError("No acceptor sessions found in settings."); + if (socketDescriptorForAddress.size() == 0){ + if (useDynamicSessions) { + // this actually stores the descriptor in the + // socketDescriptorForAddress map + getAcceptorSocketDescriptor(settings, SessionSettings.DEFAULT_SESSION_ID); + } else { + throw new ConfigError("No acceptor sessions found in settings."); + } } } Index: core/src/main/java/quickfix/Session.java =================================================================== --- core/src/main/java/quickfix/Session.java (revision 621) +++ core/src/main/java/quickfix/Session.java (working copy) @@ -22,8 +22,6 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Date; -import java.util.Map; -import java.util.WeakHashMap; import quickfix.field.BeginSeqNo; import quickfix.field.BeginString; @@ -193,8 +191,7 @@ */ public static final String SETTING_PERSIST_MESSAGES = "PersistMessages"; - // @GuardedBy(sessions) - private static final Map sessions = new WeakHashMap(); + private static ISessionDB sessionDB = new StaticSessionDB(); private final Application application; private final SessionID sessionID; @@ -229,7 +226,7 @@ private final boolean persistMessages; private final boolean checkCompID; - Session(Application application, MessageStoreFactory messageStoreFactory, SessionID sessionID, + public Session(Application application, MessageStoreFactory messageStoreFactory, SessionID sessionID, DataDictionary dataDictionary, SessionSchedule sessionSchedule, LogFactory logFactory, MessageFactory messageFactory, int heartbeatInterval) { this(application, messageStoreFactory, sessionID, dataDictionary, sessionSchedule, @@ -237,7 +234,7 @@ false, false, false, true, false, true, false); } - Session(Application application, MessageStoreFactory messageStoreFactory, SessionID sessionID, + public Session(Application application, MessageStoreFactory messageStoreFactory, SessionID sessionID, DataDictionary dataDictionary, SessionSchedule sessionSchedule, LogFactory logFactory, MessageFactory messageFactory, int heartbeatInterval, boolean checkLatency, int maxLatency, boolean millisecondsInTimeStamp, boolean resetOnLogon, @@ -424,9 +421,7 @@ } static void registerSession(Session session) { - synchronized (sessions) { - sessions.put(session.getSessionID(), session); - } + sessionDB.put(session.getSessionID(), session); } /** @@ -436,9 +431,7 @@ * @return the session, if found, or null otherwise */ public static Session lookupSession(SessionID sessionID) { - synchronized (sessions) { - return (Session) sessions.get(sessionID); - } + return (Session) sessionDB.get(sessionID); } /** @@ -1669,21 +1662,21 @@ * @return true if session exists, false otherwise. */ public static boolean doesSessionExist(SessionID sessionID) { - synchronized (sessions) { - return sessions.containsKey(sessionID); - } + return sessionDB.exists(sessionID); } - + /** * Return the session count. * @return the number of sessions */ public static int numSessions() { - synchronized (sessions) { - return sessions.size(); - } + return sessionDB.getNumSessions(); } + public static void setSessionDB(ISessionDB pSessionDB){ + sessionDB = pSessionDB; + } + /** * Sets the timeout for waiting for a logon response. * @param seconds the timeout in seconds Index: core/src/main/java/quickfix/StaticSessionDB.java =================================================================== --- core/src/main/java/quickfix/StaticSessionDB.java (revision 0) +++ core/src/main/java/quickfix/StaticSessionDB.java (revision 0) @@ -0,0 +1,31 @@ +package quickfix; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.WeakHashMap; + +public class StaticSessionDB implements ISessionDB { + Map sessionMap = Collections.synchronizedMap(new WeakHashMap()); + + public boolean exists(SessionID sessionID) { + return sessionMap.containsKey(sessionID); + } + + public Session get(SessionID sessionID) { + return (Session) sessionMap.get(sessionID); + } + + public void remove(SessionID sessionID){ + sessionMap.remove(sessionID); + } + + public void put(SessionID sessionID, Session session) { + sessionMap.put(sessionID, session); + } + + public int getNumSessions() { + return sessionMap.size(); + } + +} Property changes on: core/src/main/java/quickfix/StaticSessionDB.java ___________________________________________________________________ Name: svn:executable + * Name: svn:keywords + Id version Index: core/src/main/java/quickfix/SessionSettings.java =================================================================== --- core/src/main/java/quickfix/SessionSettings.java (revision 621) +++ core/src/main/java/quickfix/SessionSettings.java (working copy) @@ -60,7 +60,7 @@ public class SessionSettings { private Logger log = LoggerFactory.getLogger(getClass()); - private static final SessionID DEFAULT_SESSION_ID = new SessionID("DEFAULT", "", ""); + public static final SessionID DEFAULT_SESSION_ID = new SessionID("DEFAULT", "", ""); private static final String SESSION_SECTION_NAME = "session"; Index: core/src/main/java/quickfix/CachingSessionDB.java =================================================================== --- core/src/main/java/quickfix/CachingSessionDB.java (revision 0) +++ core/src/main/java/quickfix/CachingSessionDB.java (revision 0) @@ -0,0 +1,72 @@ + +package quickfix; + +import java.util.HashMap; +import java.util.Map; + +public class CachingSessionDB extends StaticSessionDB { + + Map sessionMap = new HashMap(); + SessionFactory sessionFactory; + private SessionSettings settings; + + public CachingSessionDB(){ + } + /** + * Because this implementation will create any session + * asked of it, this method always returns true. + * + * @return true + */ + public boolean exists(SessionID sessionID) { + return true; + } + + public Session get(SessionID sessionID) { + try { + synchronized(sessionMap) + { + if (sessionMap.containsKey(sessionID)){ + return (Session) sessionMap.get(sessionID); + } else { + Session newSession = null; + if (sessionFactory != null){ + newSession = sessionFactory.create(sessionID, settings); + sessionMap.put(sessionID, newSession); + } + return newSession; + } + } + } catch (ConfigError e) { + return null; + } + } + + public void remove(SessionID sessionID) { + synchronized (sessionMap) { + sessionMap.remove(sessionID); + } + } + + public SessionFactory getSessionFactory() { + return sessionFactory; + } + + public void setSessionFactory(SessionFactory sessionFactory) { + this.sessionFactory = sessionFactory; + } + + public void setDefaultSettings(SessionSettings settings){ + this.settings = settings; + } + + /** + * Technically the number of sessions is unbounded. + * + * @return Integer.MAX_VALUE + */ + public int getNumSessions() { + return Integer.MAX_VALUE; + } + +} Property changes on: core/src/main/java/quickfix/CachingSessionDB.java ___________________________________________________________________ Name: svn:executable + * Name: svn:keywords + Id version Index: core/src/main/java/quickfix/Acceptor.java =================================================================== --- core/src/main/java/quickfix/Acceptor.java (revision 621) +++ core/src/main/java/quickfix/Acceptor.java (working copy) @@ -37,4 +37,9 @@ * Acceptor setting specifying local IP interface address for accepting connections. */ public static final String SETTING_SOCKET_ACCEPT_ADDRESS = "SocketAcceptAddress"; + + /** + * Acceptor setting specifying whether to allow for dynamic session creation. + */ + public static final String SETTING_USE_DYNAMIC_SESSIONS = "UseDynamicSessions"; } \ No newline at end of file Index: core/src/main/java/quickfix/ISessionDB.java =================================================================== --- core/src/main/java/quickfix/ISessionDB.java (revision 0) +++ core/src/main/java/quickfix/ISessionDB.java (revision 0) @@ -0,0 +1,15 @@ +package quickfix; + +public interface ISessionDB { + + public void put(SessionID sessionID, Session session); + + public Session get(SessionID sessionID); + + public void remove(SessionID sessionID); + + public boolean exists(SessionID sessionID); + + public int getNumSessions(); + +} Property changes on: core/src/main/java/quickfix/ISessionDB.java ___________________________________________________________________ Name: svn:executable + * Name: svn:keywords + Id version