/*
NeoDatis ODB : Native Object Database (odb.info@neodatis.org)
Copyright (C) 2007 NeoDatis Inc. http://www.neodatis.org
"This file is part of the NeoDatis ODB open source object database".
NeoDatis ODB is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
NeoDatis ODB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package org.neodatis.odb.core.server.connection;
import java.util.List;
import java.util.Map;
import org.neodatis.odb.OID;
import org.neodatis.odb.Objects;
import org.neodatis.odb.OdbConfiguration;
import org.neodatis.odb.TransactionId;
import org.neodatis.odb.Values;
import org.neodatis.odb.core.layers.layer2.meta.ClassInfo;
import org.neodatis.odb.core.layers.layer2.meta.ClassInfoList;
import org.neodatis.odb.core.layers.layer2.meta.MetaModel;
import org.neodatis.odb.core.layers.layer2.meta.NonNativeObjectInfo;
import org.neodatis.odb.core.layers.layer2.meta.ObjectInfoHeader;
import org.neodatis.odb.core.layers.layer3.IStorageEngine;
import org.neodatis.odb.core.layers.layer3.engine.CheckMetaModelResult;
import org.neodatis.odb.core.query.QueryManager;
import org.neodatis.odb.core.query.execution.GenericQueryExecutor;
import org.neodatis.odb.core.server.layers.layer3.IODBServerExt;
import org.neodatis.odb.core.server.layers.layer3.engine.Command;
import org.neodatis.odb.core.server.layers.layer3.engine.Message;
import org.neodatis.odb.core.server.message.AddIndexMessage;
import org.neodatis.odb.core.server.message.AddIndexMessageResponse;
import org.neodatis.odb.core.server.message.CheckMetaModelCompatibilityMessage;
import org.neodatis.odb.core.server.message.CheckMetaModelCompatibilityMessageResponse;
import org.neodatis.odb.core.server.message.CloseMessage;
import org.neodatis.odb.core.server.message.CloseMessageResponse;
import org.neodatis.odb.core.server.message.CommitMessage;
import org.neodatis.odb.core.server.message.CommitMessageResponse;
import org.neodatis.odb.core.server.message.ConnectMessage;
import org.neodatis.odb.core.server.message.ConnectMessageResponse;
import org.neodatis.odb.core.server.message.CountMessage;
import org.neodatis.odb.core.server.message.CountMessageResponse;
import org.neodatis.odb.core.server.message.DeleteBaseMessage;
import org.neodatis.odb.core.server.message.DeleteBaseMessageResponse;
import org.neodatis.odb.core.server.message.DeleteIndexMessage;
import org.neodatis.odb.core.server.message.DeleteIndexMessageResponse;
import org.neodatis.odb.core.server.message.DeleteObjectMessage;
import org.neodatis.odb.core.server.message.DeleteObjectMessageResponse;
import org.neodatis.odb.core.server.message.ErrorMessage;
import org.neodatis.odb.core.server.message.GetMessage;
import org.neodatis.odb.core.server.message.GetMessageResponse;
import org.neodatis.odb.core.server.message.GetObjectFromIdMessage;
import org.neodatis.odb.core.server.message.GetObjectFromIdMessageResponse;
import org.neodatis.odb.core.server.message.GetObjectHeaderFromIdMessage;
import org.neodatis.odb.core.server.message.GetObjectHeaderFromIdMessageResponse;
import org.neodatis.odb.core.server.message.GetObjectValuesMessage;
import org.neodatis.odb.core.server.message.GetObjectValuesMessageResponse;
import org.neodatis.odb.core.server.message.GetSessionsMessage;
import org.neodatis.odb.core.server.message.GetSessionsMessageResponse;
import org.neodatis.odb.core.server.message.NewClassInfoListMessage;
import org.neodatis.odb.core.server.message.NewClassInfoListMessageResponse;
import org.neodatis.odb.core.server.message.RebuildIndexMessage;
import org.neodatis.odb.core.server.message.RebuildIndexMessageResponse;
import org.neodatis.odb.core.server.message.RollbackMessage;
import org.neodatis.odb.core.server.message.RollbackMessageResponse;
import org.neodatis.odb.core.server.message.StoreMessage;
import org.neodatis.odb.core.server.message.StoreMessageResponse;
import org.neodatis.odb.core.server.transaction.ISessionManager;
import org.neodatis.odb.core.transaction.ISession;
import org.neodatis.odb.impl.core.layers.layer3.engine.StorageEngineConstant;
import org.neodatis.odb.impl.core.query.criteria.CriteriaQuery;
import org.neodatis.odb.impl.core.server.transaction.ServerSession;
import org.neodatis.tool.DLogger;
import org.neodatis.tool.IOUtil;
import org.neodatis.tool.mutex.Mutex;
import org.neodatis.tool.mutex.MutexFactory;
import org.neodatis.tool.wrappers.OdbString;
import org.neodatis.tool.wrappers.OdbTime;
import org.neodatis.tool.wrappers.io.OdbFile;
import org.neodatis.tool.wrappers.list.IOdbList;
import org.neodatis.tool.wrappers.list.OdbArrayList;
/**
* The abstract class that manages the client server connections. It is message
* based and it manages all the client server messages.
*
* @author olivier s
*
*/
public abstract class ClientServerConnection {
private static final String LOG_ID = "ClientServerConnection";
private static int nbMessages = 0;
protected boolean connectionIsUp;
protected String baseIdentifier;
protected String connectionId;
protected boolean debug;
protected boolean automaticallyCreateDatabase;
protected IODBServerExt server;
protected ISessionManager sessionManager;
private static final String COMMIT_CLOSE_CONNECT_MUTEX_NAME = "COMMIT_CLOSE_CONNECT_MUTEX_NAME";
private static final String COUNT_MUTEX_NAME = "COUNT_MUTEX_NAME";
private static final String GET_OBJECT_HEADER_FROM_ID_MUTEX_NAME = "GET_OBJECT_HEADER_FROM_ID_MUTEX_NAME";
private static final String GET_OBJECT_FROM_ID_MUTEX_NAME = "GET_OBJECT_FROM_ID_MUTEX_NAME";
private static final String GET_VALUES_MUTEX_NAME = "GET_VALUES_MUTEX_NAME";
private static final String GET_OBJECTS_MUTEX_NAME = "GET_OBJECTS_MUTEX_NAME";
private static final String DELETE_OBJECT_MUTEX_NAME = "DELETE_OBJECT_MUTEX_NAME";
private static final String ADD_CLASS_INFO_LIST_MUTEX_NAME = "ADD_CLASS_INFO_LIST_MUTEX_NAME";
private static final String STORE_MUTEX_NAME = "STORE_MUTEX_NAME";
public ClientServerConnection(IODBServerExt server, boolean automaticallyCreateDatabase) {
this.debug = OdbConfiguration.logServerConnections();
this.automaticallyCreateDatabase = automaticallyCreateDatabase;
this.server = server;
this.sessionManager = OdbConfiguration.getCoreProvider().getClientServerSessionManager();
}
public abstract String getName();
/**
* The main method. It is the message dispatcher. Checks the message type
* and calls the right message handler.
*
* @param message
* @return
*/
public Message manageMessage(Message message) {
long start = OdbTime.getCurrentTimeInMs();
try {
nbMessages++;
int commandId = message.getCommandId();
switch (commandId) {
case Command.CONNECT:
return manageConnectCommand((ConnectMessage) message);
case Command.GET:
return manageGetObjectsCommand((GetMessage) message);
case Command.GET_OBJECT_FROM_ID:
return manageGetObjectFromIdCommand((GetObjectFromIdMessage) message);
case Command.GET_OBJECT_HEADER_FROM_ID:
return manageGetObjectHeaderFromIdCommand((GetObjectHeaderFromIdMessage) message);
case Command.STORE:
return manageStoreCommand((StoreMessage) message);
case Command.DELETE_OBJECT:
return manageDeleteObjectCommand((DeleteObjectMessage) message);
case Command.CLOSE:
return manageCloseCommand((CloseMessage) message);
case Command.COMMIT:
return manageCommitCommand((CommitMessage) message);
case Command.ROLLBACK:
return manageRollbackCommand((RollbackMessage) message);
case Command.DELETE_BASE:
return manageDeleteBaseCommand((DeleteBaseMessage) message);
case Command.GET_SESSIONS:
return manageGetSessionsCommand((GetSessionsMessage) message);
case Command.ADD_UNIQUE_INDEX:
return manageAddIndexCommand((AddIndexMessage) message);
case Command.REBUILD_INDEX:
return manageRebuildIndexCommand((RebuildIndexMessage) message);
case Command.DELETE_INDEX:
return manageDeleteIndexCommand((DeleteIndexMessage) message);
case Command.ADD_CLASS_INFO_LIST:
return manageAddClassInfoListCommand((NewClassInfoListMessage) message);
case Command.COUNT:
return manageCountCommand((CountMessage) message);
case Command.GET_OBJECT_VALUES:
return manageGetObjectValuesCommand((GetObjectValuesMessage) message);
case Command.CHECK_META_MODEL_COMPATIBILITY:
return manageCheckMetaModelCompatibilityCommand((CheckMetaModelCompatibilityMessage) message);
default:
break;
}
StringBuffer buffer = new StringBuffer();
buffer.append("ODBServer.ConnectionThread:command ").append(commandId).append(" not implemented");
return new ErrorMessage("?", "?", buffer.toString());
} finally {
long end = OdbTime.getCurrentTimeInMs();
if (debug) {
StringBuffer buffer = new StringBuffer();
buffer.append("[").append(nbMessages).append("] ");
buffer.append(message.toString()).append(" - Thread=").append(getName()).append(" - connectionId =").append(connectionId)
.append(" - duration=").append((end - start));
DLogger.info(buffer);
}
}
}
public ServerSession getSession(String baseIdentifier) {
return (ServerSession) sessionManager.getSession(baseIdentifier, true);
}
/**
* Used to check if client classes meta model is compatible with the meta
* model persisted in the database
*
* @param message
* @return
*/
private CheckMetaModelCompatibilityMessageResponse manageCheckMetaModelCompatibilityCommand(CheckMetaModelCompatibilityMessage message) {
// Gets the base identifier
String baseIdentifier = message.getBaseIdentifier();
// Gets the connection manager for this base identifier
ConnectionManager connectionManager = null;
IConnection connection = null;
try {
// Gets the connection manager for this base identifier
connectionManager = getConnectionManager(baseIdentifier);
if (connectionManager == null) {
StringBuffer buffer = new StringBuffer();
buffer.append("ODBServer.ConnectionThread:Base ").append(baseIdentifier).append(" is not registered on this server!");
return new CheckMetaModelCompatibilityMessageResponse(baseIdentifier, message.getConnectionId(), buffer.toString());
}
connection = connectionManager.getConnection(message.getConnectionId());
ServerSession session = getSession(baseIdentifier);
IStorageEngine engine = connection.getStorageEngine();
Map currentCIs = message.getCurrentCIs();
CheckMetaModelResult result = engine.checkMetaModelCompatibility(currentCIs);
MetaModel updatedMetaModel = null;
if (result.isModelHasBeenUpdated()) {
updatedMetaModel = session.getMetaModel().duplicate();
// This is to avoid message streamer think that meta model did
// not change
clearMessageStreamerCache();
}
// If meta model has been updated, returns it to clients
return new CheckMetaModelCompatibilityMessageResponse(baseIdentifier, message.getConnectionId(), result, updatedMetaModel);
} catch (Exception e) {
DLogger.error(baseIdentifier + ":Server error while closing", e);
return new CheckMetaModelCompatibilityMessageResponse(baseIdentifier, message.getConnectionId(), OdbString.exceptionToString(e,
false));
}
}
/**
* Manage Index Message
*
* @param message
* @return
*/
private Message manageAddIndexCommand(AddIndexMessage message) {
// Gets the base identifier
String baseIdentifier = message.getBaseIdentifier();
// Gets the connection manager for this base identifier
ConnectionManager connectionManager = null;
IConnection connection = null;
try {
// Gets the connection manager for this base identifier
connectionManager = getConnectionManager(baseIdentifier);
if (connectionManager == null) {
StringBuffer buffer = new StringBuffer();
buffer.append("ODBServer.ConnectionThread:Base ").append(baseIdentifier).append(" is not registered on this server!");
return new AddIndexMessageResponse(baseIdentifier, message.getConnectionId(), buffer.toString());
}
connection = connectionManager.getConnection(message.getConnectionId());
IStorageEngine engine = connection.getStorageEngine();
engine.addIndexOn(message.getClassName(), message.getIndexName(), message.getIndexFieldNames(), message.isVerbose(), message
.acceptMultipleValuesForSameKey());
} catch (Exception e) {
DLogger.error(baseIdentifier + ":Server error while closing", e);
return new AddIndexMessageResponse(baseIdentifier, message.getConnectionId(), OdbString.exceptionToString(e, false));
}
return new AddIndexMessageResponse(baseIdentifier, message.getConnectionId());
}
/**
* Rebuild an index Index Message
*
* @param message
* @return
*/
private Message manageRebuildIndexCommand(RebuildIndexMessage message) {
// Gets the base identifier
String baseIdentifier = message.getBaseIdentifier();
// Gets the connection manager for this base identifier
ConnectionManager connectionManager = null;
IConnection connection = null;
try {
// Gets the connection manager for this base identifier
connectionManager = getConnectionManager(baseIdentifier);
if (connectionManager == null) {
StringBuffer buffer = new StringBuffer();
buffer.append("ODBServer.ConnectionThread:Base ").append(baseIdentifier).append(" is not registered on this server!");
return new RebuildIndexMessageResponse(baseIdentifier, message.getConnectionId(), buffer.toString());
}
connection = connectionManager.getConnection(message.getConnectionId());
IStorageEngine engine = connection.getStorageEngine();
engine.rebuildIndex(message.getClassName(), message.getIndexName(), message.isVerbose());
} catch (Exception e) {
DLogger.error(baseIdentifier + ":Server error while closing", e);
return new RebuildIndexMessageResponse(baseIdentifier, message.getConnectionId(), OdbString.exceptionToString(e, false));
}
return new RebuildIndexMessageResponse(baseIdentifier, message.getConnectionId());
}
/**
* Delete an index Index Message
*
* @param message
* @return
*/
private Message manageDeleteIndexCommand(DeleteIndexMessage message) {
// Gets the base identifier
String baseIdentifier = message.getBaseIdentifier();
// Gets the connection manager for this base identifier
ConnectionManager connectionManager = null;
IConnection connection = null;
try {
// Gets the connection manager for this base identifier
connectionManager = getConnectionManager(baseIdentifier);
if (connectionManager == null) {
StringBuffer buffer = new StringBuffer();
buffer.append("ODBServer.ConnectionThread:Base ").append(baseIdentifier).append(" is not registered on this server!");
return new DeleteIndexMessageResponse(baseIdentifier, message.getConnectionId(), buffer.toString());
}
connection = connectionManager.getConnection(message.getConnectionId());
IStorageEngine engine = connection.getStorageEngine();
engine.deleteIndex(message.getClassName(), message.getIndexName(), message.isVerbose());
} catch (Exception e) {
DLogger.error(baseIdentifier + ":Server error while closing", e);
return new DeleteIndexMessageResponse(baseIdentifier, message.getConnectionId(), OdbString.exceptionToString(e, false));
}
return new DeleteIndexMessageResponse(baseIdentifier, message.getConnectionId());
}
private ConnectionManager getConnectionManager(String baseIdentifier) throws Exception {
return getConnectionManager(baseIdentifier, null, null, false);
}
/**
* Gets the connection manager for the base
*
* @param baseIdentifier
* @param user
* @param password
* @param returnNullIfDoesNotExit
* @return
* @throws Exception
*/
private ConnectionManager getConnectionManager(String baseIdentifier, String user, String password, boolean returnNullIfDoesNotExit)
throws Exception {
try {
// Gets the connection manager for this base identifier
ConnectionManager connectionManager = (ConnectionManager) server.getConnectionManagers().get(baseIdentifier);
if (connectionManager == null && returnNullIfDoesNotExit) {
return null;
}
if (connectionManager == null && automaticallyCreateDatabase) {
server.addBase(baseIdentifier, baseIdentifier, user, password);
connectionManager = (ConnectionManager) server.getConnectionManagers().get(baseIdentifier);
}
if (connectionManager == null && !automaticallyCreateDatabase) {
StringBuffer buffer = new StringBuffer();
buffer.append("ODBServer.ConnectionThread:Base ").append(baseIdentifier).append(" is not registered on this server!");
return null;
}
return connectionManager;
} finally {
}
}
/**
* manages the Close Message
*
* @param message
* @return
*/
private Message manageCloseCommand(CloseMessage message) {
// Gets the base identifier
String baseIdentifier = message.getBaseIdentifier();
// Gets the connection manager for this base identifier
ConnectionManager connectionManager = null;
IConnection connection = null;
Mutex mutex = null;
try {
mutex = MutexFactory.get(baseIdentifier).acquire(COMMIT_CLOSE_CONNECT_MUTEX_NAME);
// Gets the connection manager for this base identifier
connectionManager = getConnectionManager(baseIdentifier);
if (connectionManager == null) {
StringBuffer buffer = new StringBuffer();
buffer.append("ODBServer.ConnectionThread:Base ").append(baseIdentifier).append(" is not registered on this server!");
return new CloseMessageResponse(baseIdentifier, message.getConnectionId(), buffer.toString());
}
connection = connectionManager.getConnection(message.getConnectionId());
connection.setCurrentAction(ConnectionAction.ACTION_CLOSE);
connection.close();
connectionManager.removeConnection(connection);
sessionManager.removeSession(baseIdentifier);
connectionIsUp = false;
return new CloseMessageResponse(baseIdentifier, message.getConnectionId());
} catch (Exception e) {
DLogger.error(baseIdentifier + ":Server error while closing", e);
return new CloseMessageResponse(baseIdentifier, message.getConnectionId(), OdbString.exceptionToString(e, false));
} finally {
if (mutex != null) {
mutex.release("close");
}
}
}
private Message manageGetSessionsCommand(GetSessionsMessage message) {
try {
List descriptions = sessionManager.getSessionDescriptions(server.getConnectionManagers());
return new GetSessionsMessageResponse(descriptions);
} catch (Exception e) {
DLogger.error("Server error while getting session descriptions", e);
return new GetSessionsMessageResponse(OdbString.exceptionToString(e, false));
}
}
private Message manageCommitCommand(CommitMessage message) {
// Gets the base identifier
String baseIdentifier = message.getBaseIdentifier();
ConnectionManager connectionManager = null;
IConnection connection = null;
Mutex mutex = null;
try {
mutex = MutexFactory.get(baseIdentifier).acquire(COMMIT_CLOSE_CONNECT_MUTEX_NAME);
// Gets the connection manager for this base identifier
connectionManager = getConnectionManager(baseIdentifier);
if (connectionManager == null) {
StringBuffer buffer = new StringBuffer();
buffer.append("ODBServer.ConnectionThread:Base ").append(baseIdentifier).append(" is not registered on this server!");
return new CommitMessageResponse(baseIdentifier, message.getConnectionId(), buffer.toString());
}
connection = connectionManager.getConnection(message.getConnectionId());
connection.setCurrentAction(ConnectionAction.ACTION_COMMIT);
connection.commit();
return new CommitMessageResponse(baseIdentifier, message.getConnectionId(), true);
} catch (Exception e) {
DLogger.error(baseIdentifier + ":Server error while commiting", e);
return new CommitMessageResponse(baseIdentifier, message.getConnectionId(), OdbString.exceptionToString(e, false));
} finally {
if (mutex != null) {
mutex.release("commit");
}
connection.endCurrentAction();
}
}
private Message manageRollbackCommand(RollbackMessage message) {
// Gets the base identifier
String baseIdentifier = message.getBaseIdentifier();
ConnectionManager connectionManager = null;
IConnection connection = null;
Mutex mutex = null;
try {
mutex = MutexFactory.get(baseIdentifier).acquire(COMMIT_CLOSE_CONNECT_MUTEX_NAME);
// Gets the connection manager for this base identifier
connectionManager = getConnectionManager(baseIdentifier);
if (connectionManager == null) {
StringBuffer buffer = new StringBuffer();
buffer.append("ODBServer.ConnectionThread:Base ").append(baseIdentifier).append(" is not registered on this server!");
return new RollbackMessageResponse(baseIdentifier, message.getConnectionId(), buffer.toString());
}
connection = connectionManager.getConnection(message.getConnectionId());
connection.setCurrentAction(ConnectionAction.ACTION_ROLLBACK);
connection.rollback();
} catch (Exception e) {
DLogger.error(baseIdentifier + ":Server error while rollbacking", e);
return new RollbackMessageResponse(baseIdentifier, message.getConnectionId(), OdbString.exceptionToString(e, false));
} finally {
if (mutex != null) {
mutex.release("rollback");
}
connection.endCurrentAction();
}
return new RollbackMessageResponse(baseIdentifier, message.getConnectionId(), true);
}
/**
* manage the store command. The store command can be an insert(oid==null)
* or an update(oid!=null)
*
* If insert get the base mutex IF update, first get the mutex of the oid to
* update then get the base mutex, to avoid dead lock in case of concurrent
* update.
*
* @param message
* @return
*/
private Message manageStoreCommand(StoreMessage message) {
// Gets the base identifier
String baseIdentifier = message.getBaseIdentifier();
ConnectionManager connectionManager = null;
IConnection connection = null;
Mutex mutex = null;
OID oid = message.getNnoi().getOid();
ServerSession session = null;
try {
// Gets the connection manager for this base identifier
connectionManager = getConnectionManager(baseIdentifier);
if (connectionManager == null) {
StringBuffer buffer = new StringBuffer();
buffer.append("ODBServer.ConnectionThread:Base ").append(baseIdentifier).append(" is not registered on this server!");
return new StoreMessageResponse(baseIdentifier, message.getConnectionId(), buffer.toString());
}
connection = connectionManager.getConnection(message.getConnectionId());
session = getSession(baseIdentifier);
IStorageEngine engine = connection.getStorageEngine();
session.setClientIds(message.getClientIds());
boolean objectIsNew = oid == StorageEngineConstant.NULL_OBJECT_ID;
if (objectIsNew) {
connection.setCurrentAction(ConnectionAction.ACTION_INSERT);
mutex = MutexFactory.get(baseIdentifier).acquire("store");
oid = engine.writeObjectInfo(StorageEngineConstant.NULL_OBJECT_ID, message.getNnoi(),
StorageEngineConstant.POSITION_NOT_INITIALIZED, false);
} else {
connection.setCurrentAction(ConnectionAction.ACTION_UPDATE);
// If object is not new, ODB is going to execute an Update.
// Here we must lock the object with the oid to avoid a
// concurrent update
// This is done by creating a special mutex with the base
// identifier and the oid.
// This mutex will be kept in the connection and only released
// when committing
// or rollbacking the connection
connection.lockObjectWithOid(oid);
// If object lock is ok, then get the mutex of the database
mutex = MutexFactory.get(baseIdentifier).acquire(STORE_MUTEX_NAME);
// If oid is not -1, the object already exist, we must update
oid = engine.updateObject(message.getNnoi(), false);
}
return new StoreMessageResponse(baseIdentifier, message.getConnectionId(), oid, objectIsNew, message.getClientIds(), session
.getServerIds(), session.getValuesToReturn());
} catch (Exception e) {
if (oid != null) {
try {
connection.unlockObjectWithOid(message.getNnoi().getOid());
} catch (Exception e1) {
DLogger.error("Error while unlocking object with oid " + oid + " : " + OdbString.exceptionToString(e1, true));
}
}
String se = OdbString.exceptionToString(e, false);
String msg = baseIdentifier + ":Error while storing object " + message.getNnoi();
DLogger.error(msg, e);
return new StoreMessageResponse(baseIdentifier, message.getConnectionId(), msg + ":\n" + se);
} finally {
if (mutex != null) {
mutex.release("store");
}
connection.endCurrentAction();
if(session!=null){
session.clearValuesToReturn();
}
}
}
private Message manageAddClassInfoListCommand(NewClassInfoListMessage message) {
// Gets the base identifier
String baseIdentifier = message.getBaseIdentifier();
ConnectionManager connectionManager = null;
IConnection connection = null;
Mutex mutex = null;
try {
mutex = MutexFactory.get(baseIdentifier).acquire(ADD_CLASS_INFO_LIST_MUTEX_NAME);
// Gets the connection manager for this base identifier
connectionManager = getConnectionManager(baseIdentifier);
if (connectionManager == null) {
StringBuffer buffer = new StringBuffer();
buffer.append("ODBServer.ConnectionThread:Base ").append(baseIdentifier).append(" is not registered on this server!");
return new StoreMessageResponse(baseIdentifier, message.getConnectionId(), buffer.toString());
}
connection = connectionManager.getConnection(message.getConnectionId());
ServerSession session = getSession(baseIdentifier);
IStorageEngine engine = connection.getStorageEngine();
ClassInfoList ciList = message.getClassInfoList();
ciList = engine.getObjectWriter().addClasses(ciList);
// here we must create a new list with all class info because
// Serialization hold object references
// In this case, it holds the reference of the previous class info
// list. Serialization thinks object did not change so it will send
// the reference
// instead of the new object. Creating the new list force the
// serialization
// mechanism to send object
IOdbList allClassInfos = new OdbArrayList();
allClassInfos.addAll(session.getMetaModel().getAllClasses());
NewClassInfoListMessageResponse r = new NewClassInfoListMessageResponse(baseIdentifier, message.getConnectionId(),
allClassInfos);
session.resetClassInfoIds();
return r;
} catch (Exception e) {
String se = OdbString.exceptionToString(e, false);
String msg = baseIdentifier + ":Error while adding new Class Info List" + message.getClassInfoList();
DLogger.error(msg, e);
return new NewClassInfoListMessageResponse(baseIdentifier, message.getConnectionId(), msg + ":\n" + se);
} finally {
if (mutex != null) {
mutex.release("addClassInfoList");
}
}
}
private Message manageDeleteObjectCommand(DeleteObjectMessage message) {
// Gets the base identifier
String baseIdentifier = message.getBaseIdentifier();
ConnectionManager connectionManager = null;
IConnection connection = null;
Mutex mutex = null;
try {
mutex = MutexFactory.get(baseIdentifier).acquire(DELETE_OBJECT_MUTEX_NAME);
// Gets the connection manager for this base identifier
connectionManager = getConnectionManager(baseIdentifier, null, null, true);
if (connectionManager == null) {
StringBuffer buffer = new StringBuffer();
buffer.append("ODBServer.ConnectionThread:Base ").append(baseIdentifier).append(" is not registered on this server!");
return new StoreMessageResponse(baseIdentifier, message.getConnectionId(), buffer.toString());
}
connection = connectionManager.getConnection(message.getConnectionId());
connection.setCurrentAction(ConnectionAction.ACTION_DELETE);
ServerSession session = (ServerSession) sessionManager.getSession(baseIdentifier, true);
IStorageEngine engine = connection.getStorageEngine();
engine.deleteObjectWithOid(message.getOid(),message.isCascade());
return new DeleteObjectMessageResponse(baseIdentifier, message.getConnectionId(), message.getOid());
} catch (Exception e) {
String se = OdbString.exceptionToString(e, false);
String msg = baseIdentifier + ":Error while deleting object " + message.getOid();
DLogger.error(msg, e);
return new DeleteObjectMessageResponse(baseIdentifier, message.getConnectionId(), msg + ":\n" + se);
} finally {
if (mutex != null) {
mutex.release("deleteObject");
}
connection.endCurrentAction();
}
}
private Message manageDeleteBaseCommand(DeleteBaseMessage message) {
// Gets the base identifier
String baseIdentifier = message.getBaseIdentifier();
ConnectionManager connectionManager = null;
try {
// Gets the connection manager for this base identifier
connectionManager = getConnectionManager(baseIdentifier, null, null, true);
StringBuffer log = new StringBuffer();
String fileName = message.getBaseIdentifier();
OdbFile file = new OdbFile(fileName);
if (connectionManager == null) {
try {
if (debug) {
log.append("Server:Connection manager is null Deleting base " + file.getFullPath()).append(" | exists?").append(file.exists());
}
if (file.exists()) {
boolean b = IOUtil.deleteFile(file.getFullPath());
if (debug) {
log.append("| deleted=").append(b);
}
b = !file.exists();
if (debug) {
log.append("| deleted=").append(b);
}
if (b) {
return new DeleteBaseMessageResponse(baseIdentifier);
}
return new DeleteBaseMessageResponse(baseIdentifier, "[1] could not delete base " + file.getFullPath());
}
return new DeleteBaseMessageResponse(baseIdentifier);
} finally {
if (debug) {
DLogger.info(log.toString());
}
}
}
IStorageEngine engine = connectionManager.getStorageEngine();
if (!engine.isClosed()) {
// Simulate a session
sessionManager.addSession(OdbConfiguration.getCoreProvider().getServerSession(engine, "temp"));
// engine.rollback();
engine.close();
sessionManager.removeSession(baseIdentifier);
removeConnectionManager(baseIdentifier);
}
boolean b = IOUtil.deleteFile(fileName);
log.append("| deleted=").append(b);
if (b) {
return new DeleteBaseMessageResponse(baseIdentifier);
}
return new DeleteBaseMessageResponse(baseIdentifier, "[2] could not delete base "
+ new OdbFile(message.getBaseIdentifier()).getFullPath());
} catch (Exception e) {
String se = OdbString.exceptionToString(e, false);
String msg = baseIdentifier + ":Error while deleting base " + message.getBaseIdentifier();
DLogger.error(msg, e);
return new DeleteBaseMessageResponse(baseIdentifier, msg + ":\n" + se);
} finally {
sessionManager.removeSession(baseIdentifier);
removeConnectionManager(baseIdentifier);
connectionIsUp = false;
}
}
private void removeConnectionManager(String baseId) {
server.getConnectionManagers().remove(baseId);
}
private Message manageGetObjectsCommand(GetMessage message) {
// Gets the base identifier
String baseIdentifier = message.getBaseIdentifier();
// Gets the connection manager for this base identifier
ConnectionManager connectionManager = null;
IConnection connection = null;
Mutex mutex = null;
try {
mutex = MutexFactory.get(baseIdentifier).acquire(GET_OBJECTS_MUTEX_NAME);
// Gets the connection manager for this base identifier
connectionManager = getConnectionManager(baseIdentifier);
if (connectionManager == null) {
StringBuffer buffer = new StringBuffer();
buffer.append("ODBServer.ConnectionThread:Base ").append(baseIdentifier).append(" is not registered on this server!");
return new GetMessageResponse(baseIdentifier, message.getConnectionId(), buffer.toString());
}
connection = connectionManager.getConnection(message.getConnectionId());
connection.setCurrentAction(ConnectionAction.ACTION_SELECT);
if (OdbConfiguration.lockObjectsOnSelect()) {
// first lock the class
String fullClassName = QueryManager.getFullClassName(message.getQuery());
//connection.lockClass(fullClassName);
}
IStorageEngine engine = connection.getStorageEngine();
Objects metaObjects = null;
metaObjects = engine.getObjectInfos(message.getQuery(), true, message.getStartIndex(), message.getEndIndex(), false);
if (OdbConfiguration.lockObjectsOnSelect()) {
// then lock objects
while(metaObjects.hasNext()){
OID oid = metaObjects.next().getOid();
connection.lockObjectWithOid(oid);
System.out.println("locking object with oid " + oid);
}
// and unlock class
String fullClassName = QueryManager.getFullClassName(message.getQuery());
//connection.unlockClass(fullClassName);
}
// message.getQuery().setStorageEngine(null);
return new GetMessageResponse(baseIdentifier, message.getConnectionId(), metaObjects, message.getQuery().getExecutionPlan());
} catch (Exception e) {
String se = OdbString.exceptionToString(e, false);
String msg = baseIdentifier + ":Error while getting objects for query " + message.getQuery();
DLogger.error(msg, e);
return new GetMessageResponse(baseIdentifier, message.getConnectionId(), msg + ":\n" + se);
} finally {
if (mutex != null) {
mutex.release("getObjects");
}
connection.endCurrentAction();
}
}
private Message manageGetObjectValuesCommand(GetObjectValuesMessage message) {
// Gets the base identifier
String baseIdentifier = message.getBaseIdentifier();
// Gets the connection manager for this base identifier
ConnectionManager connectionManager = null;
IConnection connection = null;
Mutex mutex = null;
try {
mutex = MutexFactory.get(baseIdentifier).acquire(GET_VALUES_MUTEX_NAME);
// Gets the connection manager for this base identifier
connectionManager = getConnectionManager(baseIdentifier);
if (connectionManager == null) {
StringBuffer buffer = new StringBuffer();
buffer.append("ODBServer.ConnectionThread:Base ").append(baseIdentifier).append(" is not registered on this server!");
return new GetMessageResponse(baseIdentifier, message.getConnectionId(), buffer.toString());
}
connection = connectionManager.getConnection(message.getConnectionId());
connection.setCurrentAction(ConnectionAction.ACTION_SELECT);
IStorageEngine engine = connection.getStorageEngine();
Values values = engine.getValues(message.getQuery(), message.getStartIndex(), message.getEndIndex());
return new GetObjectValuesMessageResponse(baseIdentifier, message.getConnectionId(), values, message.getQuery()
.getExecutionPlan());
} catch (Exception e) {
String se = OdbString.exceptionToString(e, false);
String msg = baseIdentifier + ":Error while getting objects for query " + message.getQuery();
DLogger.error(msg, e);
return new GetObjectValuesMessageResponse(baseIdentifier, message.getConnectionId(), msg + ":\n" + se);
} finally {
if (mutex != null) {
mutex.release("getObjects");
}
connection.endCurrentAction();
}
}
private Message manageGetObjectFromIdCommand(GetObjectFromIdMessage message) {
// Gets the base identifier
String baseIdentifier = message.getBaseIdentifier();
// Gets the connection manager for this base identifier
ConnectionManager connectionManager = null;
IConnection connection = null;
OID oid = null;
Mutex mutex = null;
try {
mutex = MutexFactory.get(baseIdentifier).acquire(GET_OBJECT_FROM_ID_MUTEX_NAME);
// Gets the connection manager for this base identifier
connectionManager = getConnectionManager(baseIdentifier);
if (connectionManager == null) {
StringBuffer buffer = new StringBuffer();
buffer.append("ODBServer.ConnectionThread:Base ").append(baseIdentifier).append(" is not registered on this server!");
return new GetObjectFromIdMessageResponse(baseIdentifier, message.getConnectionId(), buffer.toString());
}
connection = connectionManager.getConnection(message.getConnectionId());
connection.setCurrentAction(ConnectionAction.ACTION_SELECT);
IStorageEngine engine = connection.getStorageEngine();
oid = message.getOid();
NonNativeObjectInfo nnoi = engine.getMetaObjectFromOid(oid);
return new GetObjectFromIdMessageResponse(baseIdentifier, message.getConnectionId(), nnoi);
} catch (Exception e) {
String se = OdbString.exceptionToString(e, false);
String msg = baseIdentifier + ":Error while getting object of id " + oid;
DLogger.error(msg, e);
return new GetObjectFromIdMessageResponse(baseIdentifier, message.getConnectionId(), msg + ":\n" + se);
} finally {
if (mutex != null) {
mutex.release("getObjectFromId");
}
connection.endCurrentAction();
}
}
private Message manageGetObjectHeaderFromIdCommand(GetObjectHeaderFromIdMessage message) {
// Gets the base identifier
String baseIdentifier = message.getBaseIdentifier();
// Gets the connection manager for this base identifier
ConnectionManager connectionManager = null;
IConnection connection = null;
OID oid = null;
Mutex mutex = null;
try {
mutex = MutexFactory.get(baseIdentifier).acquire(GET_OBJECT_HEADER_FROM_ID_MUTEX_NAME);
// Gets the connection manager for this base identifier
connectionManager = getConnectionManager(baseIdentifier);
if (connectionManager == null) {
StringBuffer buffer = new StringBuffer();
buffer.append("ODBServer.ConnectionThread:Base ").append(baseIdentifier).append(" is not registered on this server!");
return new GetObjectHeaderFromIdMessageResponse(baseIdentifier, message.getConnectionId(), buffer.toString());
}
connection = connectionManager.getConnection(message.getConnectionId());
connection.setCurrentAction(ConnectionAction.ACTION_SELECT);
IStorageEngine engine = connection.getStorageEngine();
oid = message.getOid();
ObjectInfoHeader oih = engine.getObjectInfoHeaderFromOid(oid, message.useCache());
// the oih.duplicate method is called to create a new instance of
// the ObjectInfoHeader becasue of
// the java Serialization problem : Serialization will check the
// reference of the object and only send the reference if the object
// has already
// been changed. => creating a new will avoid this problem
return new GetObjectHeaderFromIdMessageResponse(baseIdentifier, message.getConnectionId(), oih.duplicate());
} catch (Exception e) {
String se = OdbString.exceptionToString(e, false);
String msg = baseIdentifier + ":Error while getting object of id " + oid;
DLogger.error(msg, e);
return new GetObjectHeaderFromIdMessageResponse(baseIdentifier, message.getConnectionId(), msg + ":\n" + se);
} finally {
if (mutex != null) {
mutex.release("getObjectFromId");
}
connection.endCurrentAction();
}
}
private Message manageCountCommand(CountMessage message) {
// Gets the base identifier
String baseIdentifier = message.getBaseIdentifier();
// Gets the connection manager for this base identifier
ConnectionManager connectionManager = null;
IConnection connection = null;
Mutex mutex = null;
try {
mutex = MutexFactory.get(baseIdentifier).acquire(COUNT_MUTEX_NAME);
// Gets the connection manager for this base identifier
connectionManager = getConnectionManager(baseIdentifier);
if (connectionManager == null) {
StringBuffer buffer = new StringBuffer();
buffer.append("ODBServer.ConnectionThread:Base ").append(baseIdentifier).append(" is not registered on this server!");
return new GetObjectFromIdMessageResponse(baseIdentifier, message.getConnectionId(), buffer.toString());
}
connection = connectionManager.getConnection(message.getConnectionId());
IStorageEngine engine = connection.getStorageEngine();
CriteriaQuery query = message.getCriteriaQuery();
long nbObjects = engine.count(query);
return new CountMessageResponse(baseIdentifier, message.getConnectionId(), nbObjects);
} catch (Exception e) {
String se = OdbString.exceptionToString(e, false);
String msg = baseIdentifier + ":Error while counting objects for " + message.getCriteriaQuery();
DLogger.error(msg, e);
return new CountMessageResponse(baseIdentifier, message.getConnectionId(), msg + ":\n" + se);
} finally {
if (mutex != null) {
mutex.release("count");
}
}
}
private Message manageConnectCommand(ConnectMessage message) {
// Gets the base identifier
baseIdentifier = message.getBaseIdentifier();
// Gets the connection manager for this base identifier
ConnectionManager connectionManager = null;
IConnection connection = null;
Mutex mutex = null;
try {
mutex = MutexFactory.get(baseIdentifier).acquire(COMMIT_CLOSE_CONNECT_MUTEX_NAME);
// Gets the connection manager for this base identifier
connectionManager = getConnectionManager(baseIdentifier, message.getUser(), message.getPassword(), false);
if (connectionManager == null) {
StringBuffer buffer = new StringBuffer();
buffer.append("Base ").append(baseIdentifier).append(" is not registered on this server!");
return new ConnectMessageResponse(baseIdentifier, "?", buffer.toString());
}
String ip = message.getIp();
long dateTime = message.getDateTime();
connection = connectionManager.newConnection(ip, dateTime, connectionManager.getNbConnections());
connection.setCurrentAction(ConnectionAction.ACTION_CONNECT);
connectionId = connection.getId();
// Creates a new session for this connection
ISession session = new ServerSession(connection.getStorageEngine(), connectionId);
IStorageEngine engine = connection.getStorageEngine();
// adds the session to the storage engine (it will be associated to
// the current thread
// The add session sets the correct meta model
engine.addSession(session, true);
TransactionId transactionId = engine.getCurrentTransactionId();
if (debug) {
DLogger.info(new StringBuffer("Connection from ").append(ip).append(" - cid=").append(connection.getId()).append(
" - session=").append(session.getId()).append(" - Base Id=").append(baseIdentifier).toString());
}
// Returns the meta-model to the client
MetaModel metaModel = engine.getSession(true).getMetaModel();
ConnectMessageResponse cmr = new ConnectMessageResponse(baseIdentifier, connection.getId(), metaModel, transactionId);
return cmr;
} catch (Exception e) {
String se = OdbString.exceptionToString(e, false);
String msg = baseIdentifier + ":Error while connecting to " + message.getBaseIdentifier();
DLogger.error(msg, e);
return new ConnectMessageResponse(baseIdentifier, message.getConnectionId(), msg + ":\n" + se);
} finally {
if (mutex != null) {
mutex.release("connect");
}
if (connection != null) {
connection.endCurrentAction();
}
}
}
public abstract void clearMessageStreamerCache();
}
Ads help maintain this website.