/* This file is part of the db4o object database http://www.db4o.com Copyright (C) 2004 - 2011 Versant Corporation http://www.versant.com db4o is free software; you can redistribute it and/or modify it under the terms of version 3 of the GNU General Public License as published by the Free Software Foundation. db4o 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/. */ package com.db4o.cs.internal.messages; import com.db4o.*; import com.db4o.cs.internal.*; import com.db4o.ext.*; import com.db4o.foundation.*; import com.db4o.internal.*; /** * Messages for Client/Server Communication */ public abstract class Msg implements Cloneable, Message { static int _messageIdGenerator = 1; private static Msg[] _messages = new Msg[75]; int _msgID; String _name; private Transaction _trans; private MessageDispatcher _messageDispatcher; public static final MRuntimeException RUNTIME_EXCEPTION = new MRuntimeException(); public static final MClassID CLASS_ID = new MClassID(); public static final MClassMetadataIdForName CLASS_METADATA_ID_FOR_NAME = new MClassMetadataIdForName(); public static final MClassNameForID CLASS_NAME_FOR_ID = new MClassNameForID(); public static final MClose CLOSE = new MClose(); public static final MCloseSocket CLOSE_SOCKET = new MCloseSocket(); public static final MCommit COMMIT = new MCommit(); public static final MCommittedCallBackRegistry COMMITTED_CALLBACK_REGISTER = new MCommittedCallBackRegistry(); public static final MCommittedInfo COMMITTED_INFO = new MCommittedInfo(); public static final MCommitSystemTransaction COMMIT_SYSTEMTRANS = new MCommitSystemTransaction(); public static final MCreateClass CREATE_CLASS = new MCreateClass(); public static final MClassMeta CLASS_META = new MClassMeta(); public static final MVersion CURRENT_VERSION = new MVersion(); public static final MDelete DELETE = new MDelete(); public static final MError ERROR = new MError(); public static final MFailed FAILED = new MFailed(); public static final MGetAll GET_ALL = new MGetAll(); public static final MGetClasses GET_CLASSES = new MGetClasses(); public static final MGetInternalIDs GET_INTERNAL_IDS = new MGetInternalIDs(); public static final MGetThreadID GET_THREAD_ID = new MGetThreadID(); public static final MIDList ID_LIST = new MIDList(); public static final MIdentity IDENTITY = new MIdentity(); public static final MIsAlive IS_ALIVE = new MIsAlive(); public static final MLength LENGTH = new MLength(); public static final MLogin LOGIN = new MLogin(); public static final MLoginOK LOGIN_OK = new MLoginOK(); public static final MNull NULL = new MNull(); public static final MObjectByUuid OBJECT_BY_UUID = new MObjectByUuid(); public static final MsgObject OBJECT_TO_CLIENT = new MsgObject(); public static final MObjectSetFetch OBJECTSET_FETCH = new MObjectSetFetch(); public static final MObjectSetFinalized OBJECTSET_FINALIZED = new MObjectSetFinalized(); public static final MObjectSetGetId OBJECTSET_GET_ID = new MObjectSetGetId(); public static final MObjectSetIndexOf OBJECTSET_INDEXOF = new MObjectSetIndexOf(); public static final MObjectSetReset OBJECTSET_RESET = new MObjectSetReset(); public static final MObjectSetSize OBJECTSET_SIZE = new MObjectSetSize(); public static final MOK OK = new MOK(); public static final MPing PING = new MPing(); public static final MPong PONG = new MPong(); public static final MPrefetchIDs PREFETCH_IDS = new MPrefetchIDs(); public static final MProcessDeletes PROCESS_DELETES = new MProcessDeletes(); public static final MQueryExecute QUERY_EXECUTE = new MQueryExecute(); public static final MQueryResult QUERY_RESULT = new MQueryResult(); public static final MRaiseCommitTimestamp RAISE_COMMIT_TIMESTAMP = new MRaiseCommitTimestamp(); public static final MReadBlob READ_BLOB = new MReadBlob(); public static final MReadBytes READ_BYTES = new MReadBytes(); public static final MReadSlot READ_SLOT = new MReadSlot(); public static final MReadMultipleObjects READ_MULTIPLE_OBJECTS = new MReadMultipleObjects(); public static final MReadObject READ_OBJECT = new MReadObject(); public static final MReadReaderById READ_READER_BY_ID = new MReadReaderById(); public static final MReleaseSemaphore RELEASE_SEMAPHORE = new MReleaseSemaphore(); public static final MRollback ROLLBACK = new MRollback(); public static final MSetSemaphore SET_SEMAPHORE = new MSetSemaphore(); public static final MSuccess SUCCESS = new MSuccess(); public static final MSwitchToFile SWITCH_TO_FILE = new MSwitchToFile(); public static final MSwitchToMainFile SWITCH_TO_MAIN_FILE = new MSwitchToMainFile(); public static final MTaDelete TA_DELETE = new MTaDelete(); public static final MTaIsDeleted TA_IS_DELETED = new MTaIsDeleted(); public static final MUserMessage USER_MESSAGE = new MUserMessage(); public static final MUseTransaction USE_TRANSACTION = new MUseTransaction(); public static final MWriteBlob WRITE_BLOB = new MWriteBlob(); public static final MWriteNew WRITE_NEW = new MWriteNew(); public static final MWriteUpdate WRITE_UPDATE = new MWriteUpdate(); public static final MWriteBatchedMessages WRITE_BATCHED_MESSAGES = new MWriteBatchedMessages(); public static final MsgBlob DELETE_BLOB_FILE = new MDeleteBlobFile(); public static final MInstanceCount INSTANCE_COUNT = new MInstanceCount(); public static final MRequestExceptionWithResponse REQUEST_EXCEPTION_WITH_RESPONSE = new MRequestExceptionWithResponse(); public static final MRequestExceptionWithoutResponse REQUEST_EXCEPTION_WITHOUT_RESPONSE = new MRequestExceptionWithoutResponse(); public static final MCommitReplication COMMIT_REPLICATION = new MCommitReplication(); public static final MGenerateTransactionTimestamp GENERATE_TRANSACTION_TIMESTAMP = new MGenerateTransactionTimestamp(); public static final MVersionForId VERSION_FOR_ID = new MVersionForId(); public static final MUseDefaultTransactionTimestamp USE_DEFAULT_TRANSACTION_TIMESTAMP = new MUseDefaultTransactionTimestamp(); Msg() { _msgID = _messageIdGenerator++; _messages[_msgID] = this; } Msg(String aName) { this(); _name = aName; } public static Msg getMessage(int id) { return _messages[id]; } public final Msg publicClone() { try { return (Msg)clone(); } catch (CloneNotSupportedException e) { Exceptions4.shouldNeverHappen(); return null; } } public final boolean equals(Object obj) { if(this==obj) { return true; } if(obj==null||obj.getClass()!=this.getClass()) { return false; } return _msgID == ((Msg) obj)._msgID; } public int hashCode() { return _msgID; } /** * dummy method to allow clean override handling * without casting */ public ByteArrayBuffer getByteLoad() { return null; } final String getName() { if (_name == null) { return getClass().getName(); } return _name; } protected LocalTransaction serverTransaction(){ return (LocalTransaction)_trans; } protected Transaction transaction() { return _trans; } protected LocalObjectContainer localContainer(){ return (LocalObjectContainer)container(); } protected ObjectContainerBase container(){ return transaction().container(); } protected Object containerLock(){ return container().lock(); } protected Config4Impl config(){ return container().config(); } protected static StatefulBuffer readMessageBuffer(Transaction trans, Socket4Adapter socket) throws Db4oIOException { return readMessageBuffer(trans, socket, Const4.MESSAGE_LENGTH); } protected static StatefulBuffer readMessageBuffer(Transaction trans, Socket4Adapter socket, int length) throws Db4oIOException { StatefulBuffer buffer = new StatefulBuffer(trans, length); int offset = 0; while (length > 0) { int read = socket.read(buffer._buffer, offset, length); if(read < 0) { throw new Db4oIOException(); } offset += read; length -= read; } return buffer; } public static final Msg readMessage(MessageDispatcher messageDispatcher, Transaction trans, Socket4Adapter socket) throws Db4oIOException { StatefulBuffer reader = readMessageBuffer(trans, socket); Msg message = _messages[reader.readInt()].readPayLoad(messageDispatcher, trans, socket, reader); if (Debug4.messages) { System.out.println(message + " arrived at " + trans.container()); } return message; } /** @param socket */ Msg readPayLoad(MessageDispatcher messageDispatcher, Transaction a_trans, Socket4Adapter socket, ByteArrayBuffer reader){ Msg msg = publicClone(); msg.setMessageDispatcher(messageDispatcher); msg.setTransaction(checkParentTransaction(a_trans, reader)); return msg; } protected final Transaction checkParentTransaction(Transaction a_trans, ByteArrayBuffer reader) { if(reader.readByte() == Const4.SYSTEM_TRANS && a_trans.parentTransaction() != null){ return a_trans.parentTransaction(); } return a_trans; } public final void setTransaction(Transaction aTrans) { _trans = aTrans; } final public String toString() { return getName(); } public void write(Msg msg) { _messageDispatcher.write(msg); } public void writeException(RuntimeException e) { write(RUNTIME_EXCEPTION.getWriterForSingleObject(transaction(), e)); } public Msg respondInt(int response){ return ID_LIST.getWriterForInt(transaction(), response); } public boolean write(Socket4Adapter sock) { if (null == sock) { throw new ArgumentNullException(); } synchronized (sock) { try { if (Debug4.messages) { System.out.println(this +" sent by " + Thread.currentThread().getName()); } sock.write(payLoad()._buffer); sock.flush(); return true; } catch (Exception e) { // TODO: .NET convert SocketException to Db4oIOException // and let Db4oIOException bubble up. //e.printStackTrace(); return false; } } } public StatefulBuffer payLoad() { StatefulBuffer writer = new StatefulBuffer(transaction(), Const4.MESSAGE_LENGTH); writer.writeInt(_msgID); return writer; } public MessageDispatcher messageDispatcher() { return _messageDispatcher; } public ServerMessageDispatcher serverMessageDispatcher() { if(_messageDispatcher instanceof ServerMessageDispatcher) { return (ServerMessageDispatcher) _messageDispatcher; } throw new IllegalStateException(); } public ClientMessageDispatcher clientMessageDispatcher() { if(_messageDispatcher instanceof ClientMessageDispatcher) { return (ClientMessageDispatcher) _messageDispatcher; } throw new IllegalStateException(); } public void setMessageDispatcher(MessageDispatcher messageDispatcher) { _messageDispatcher = messageDispatcher; } public void logMsg(int msgCode, String msg) { container().logMsg(msgCode, msg); } /** to be overridden by implementors of MessageWithResponse */ public void postProcessAtServer() { // do nothing by default } protected Transaction systemTransaction() { return container().systemTransaction(); } }