in database-jones/Adapter/api/UserContext.js [414:589]
var getSessionFactory = function(userContext, properties, tableMappings, callback) {
var database;
var dbServiceProvider;
var connectionKey;
var connection;
var factory;
var newSession;
var sp;
var i;
function Connection(connectionKey) {
this.connectionKey = connectionKey;
this.factories = {};
this.count = 0;
this.isConnecting = true;
this.waitingForConnection = [];
}
function newConnection(connectionKey) {
var c = new Connection(connectionKey);
jonesConnections[connectionKey] = c;
return c;
}
function getConnection(connectionKey) {
return jonesConnections[connectionKey];
}
function deleteFactory(key, database, callback) {
udebug.log('deleteFactory for key', key, 'database', database);
var c = jonesConnections[key];
var f = c.factories[database];
var dbConnectionPool = f.dbConnectionPool;
delete c.factories[database];
if (--connection.count === 0) {
// no more factories in this connection
udebug.log('deleteFactory closing dbConnectionPool for key', key, 'database', database);
dbConnectionPool.close(callback);
dbConnectionPool = null;
delete jonesConnections[key];
} else {
callback();
}
}
function resolveTableMappingsAndCallback() {
function onMappingsResolved() {
// close the session the hard way (not using UserContext)
newSession.dbSession.close(function(err) {
if (err) {
callback(err, null);
} else {
// now remove the session from the session factory's open connections
newSession.sessionFactory.closeSession(newSession.index);
// mark this session as unusable
newSession.closed = true;
// if any errors during table mapping, report them
if (userContext.errorMessages) {
err = reportFirstError(userContext);
callback(err, null);
} else {
// no errors
callback(null, factory);
}
}
});
}
// resolveTableMappingsAndCallback starts here
if (!tableMappings) {
callback(null, factory);
} else {
// get a session the hard way (not using UserContext) to resolve mappings
var sessionSlot = factory.allocateSessionSlot();
factory.dbConnectionPool.getDBSession(userContext.session_index, function(err, dbSession) {
if (err) {
// report error
userContext.appendErrorMessage(err);
err = new Error(userContext.errorMessages);
callback(err, null);
} else {
newSession = new apiSession.Session(sessionSlot, factory, dbSession);
factory.sessions[sessionSlot] = newSession;
resolveTableMappings(userContext, factory, newSession, tableMappings, onMappingsResolved);
}
});
}
}
function createFactory(dbConnectionPool) {
var newFactory;
udebug.log('connect createFactory creating factory for', connectionKey, 'database', database);
newFactory = new sessionFactory.SessionFactory(connectionKey, dbConnectionPool,
properties, tableMappings, deleteFactory);
return newFactory;
}
function dbConnectionPoolCreated_callback(error, dbConnectionPool) {
if (connection.isConnecting) {
// the first requester for this connection
connection.isConnecting = false;
// remember the error condition
connection.error = error;
if (error) {
callback(error, null);
} else {
udebug.log('dbConnectionPool created for', connectionKey, 'database', database);
connection.dbConnectionPool = dbConnectionPool;
factory = createFactory(dbConnectionPool);
connection.factories[database] = factory;
connection.count++;
resolveTableMappingsAndCallback();
}
// notify all others that the connection is now ready (or an error was signaled)
for (i = 0; i < connection.waitingForConnection.length; ++i) {
if(udebug.is_detail()) { udebug.log('dbConnectionPoolCreated_callback notifying...'); }
connection.waitingForConnection[i](error, dbConnectionPool);
}
} else {
// another user request created the dbConnectionPool and session factory
if (error) {
callback(error, null);
} else {
udebug.log('dbConnectionPoolCreated_callback', database, connection.factories);
factory = connection.factories[database];
if (!factory) {
factory = createFactory(dbConnectionPool);
connection.factories[database] = factory;
connection.count++;
}
resolveTableMappingsAndCallback();
}
}
}
// getSessionFactory starts here
database = properties.database;
dbServiceProvider = jones.getDBServiceProvider(properties.implementation);
connectionKey = dbServiceProvider.getFactoryKey(properties);
connection = getConnection(connectionKey);
if(connection === undefined) {
// there is no connection yet using this connection key
udebug.log('connect connection does not exist; creating factory for',
connectionKey, 'database', database);
connection = newConnection(connectionKey);
sp = jones.getDBServiceProvider(properties.implementation);
sp.connect(properties, dbConnectionPoolCreated_callback);
} else {
// there is a connection, but is it already connected?
if (connection.isConnecting) {
// wait until the first requester for this connection completes
udebug.log('connect waiting for db connection by another for', connectionKey, 'database', database);
connection.waitingForConnection.push(dbConnectionPoolCreated_callback);
} else {
// there is a connection, but is there a SessionFactory for this database?
factory = connection.factories[database];
if ( factory === undefined) {
if (!connection.dbConnectionPool) {
// this connection is unusable due to failure reported in connection.error
callback(connection.error);
return;
}
// create a SessionFactory for the existing dbConnectionPool
udebug.log('connect creating factory with existing', connectionKey, 'database', database);
factory = createFactory(connection.dbConnectionPool);
connection.factories[database] = factory;
connection.count++;
}
// resolve all table mappings before returning
resolveTableMappingsAndCallback();
}
}
};