/* 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 java.io.*; import com.db4o.cs.internal.*; import com.db4o.ext.*; import com.db4o.foundation.*; import com.db4o.internal.*; /** * @exclude */ public class MCommittedInfo extends MsgD implements ClientSideMessage { public MCommittedInfo encode(CallbackObjectInfoCollections callbackInfo, int dispatcherID) { ByteArrayOutputStream os = new ByteArrayOutputStream(); PrimitiveCodec.writeInt(os, dispatcherID); byte[] bytes = encodeInfo(callbackInfo, os); MCommittedInfo committedInfo = (MCommittedInfo) getWriterForLength(transaction(), bytes.length + Const4.INT_LENGTH); committedInfo._payLoad.append(bytes); return committedInfo; } private byte[] encodeInfo(CallbackObjectInfoCollections callbackInfo, ByteArrayOutputStream os) { encodeObjectInfoCollection(os, callbackInfo.added, new InternalIDEncoder()); encodeObjectInfoCollection(os, callbackInfo.deleted, new FrozenObjectInfoEncoder()); encodeObjectInfoCollection(os, callbackInfo.updated, new InternalIDEncoder()); return os.toByteArray(); } private final class FrozenObjectInfoEncoder implements ObjectInfoEncoder { public void encode(ByteArrayOutputStream os, ObjectInfo info) { PrimitiveCodec.writeLong(os, info.getInternalID()); long sourceDatabaseId = ((FrozenObjectInfo)info).sourceDatabaseId(transaction()); PrimitiveCodec.writeLong(os, sourceDatabaseId); PrimitiveCodec.writeLong(os, ((FrozenObjectInfo)info).uuidLongPart()); PrimitiveCodec.writeLong(os, info.getCommitTimestamp()); } public ObjectInfo decode(ByteArrayInputStream is) { long id = PrimitiveCodec.readLong(is); if (id == -1) { return null; } long sourceDatabaseId = PrimitiveCodec.readLong(is); Db4oDatabase sourceDatabase = null; if (sourceDatabaseId > 0 ){ sourceDatabase = (Db4oDatabase) container().getByID(transaction(), sourceDatabaseId); } long uuidLongPart = PrimitiveCodec.readLong(is); long version = PrimitiveCodec.readLong(is); return new FrozenObjectInfo(null, id, sourceDatabase, uuidLongPart, version); } } private final class InternalIDEncoder implements ObjectInfoEncoder { public void encode(ByteArrayOutputStream os, ObjectInfo info) { PrimitiveCodec.writeLong(os, info.getInternalID()); } public ObjectInfo decode(ByteArrayInputStream is) { long id = PrimitiveCodec.readLong(is); if (id == -1) { return null; } return new LazyObjectReference(transaction(), (int) id); } } interface ObjectInfoEncoder { void encode(ByteArrayOutputStream os, ObjectInfo info); ObjectInfo decode(ByteArrayInputStream is); } private void encodeObjectInfoCollection(ByteArrayOutputStream os, ObjectInfoCollection collection, final ObjectInfoEncoder encoder) { Iterator4 iter = collection.iterator(); while (iter.moveNext()) { ObjectInfo obj = (ObjectInfo) iter.current(); encoder.encode(os, obj); } PrimitiveCodec.writeLong(os, -1); } public CallbackObjectInfoCollections decode(ByteArrayInputStream is) { final ObjectInfoCollection added = decodeObjectInfoCollection(is, new InternalIDEncoder()); final ObjectInfoCollection deleted = decodeObjectInfoCollection(is, new FrozenObjectInfoEncoder()); final ObjectInfoCollection updated = decodeObjectInfoCollection(is, new InternalIDEncoder()); return new CallbackObjectInfoCollections(added, updated, deleted); } private ObjectInfoCollection decodeObjectInfoCollection(ByteArrayInputStream is, ObjectInfoEncoder encoder){ final Collection4 collection = new Collection4(); while (true) { ObjectInfo info = encoder.decode(is); if (null == info) { break; } collection.add(info); } return new ObjectInfoCollectionImpl(collection); } public boolean processAtClient() { ByteArrayInputStream is = new ByteArrayInputStream(_payLoad._buffer); final int dispatcherID = PrimitiveCodec.readInt(is); final CallbackObjectInfoCollections callbackInfos = decode(is); container().threadPool().start(ReflectPlatform.simpleName(getClass())+": calling commit callbacks thread", new Runnable() { public void run() { if(container().isClosed()){ return; } container().callbacks().commitOnCompleted(transaction(), callbackInfos, dispatcherID == ((ClientObjectContainer)container()).serverSideID()); } }); return true; } protected void writeByteArray(ByteArrayOutputStream os, byte[] signaturePart) throws IOException { PrimitiveCodec.writeLong(os, signaturePart.length); os.write(signaturePart); } }