/* * Copyright (C) 2012, 2016 higherfrequencytrading.com * Copyright (C) 2016 Roman Leventov * * This program 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 3 of the License. * * This program 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 program. If not, see <http://www.gnu.org/licenses/>. */ package net.openhft.chronicle.map.impl.stage.input; import net.openhft.chronicle.bytes.Bytes; import net.openhft.chronicle.hash.Data; import net.openhft.chronicle.hash.impl.stage.entry.SegmentStages; import net.openhft.chronicle.hash.impl.stage.hash.CheckOnEachPublicOperation; import net.openhft.chronicle.hash.replication.RemoteOperationContext; import net.openhft.chronicle.map.Replica; import net.openhft.chronicle.map.impl.ReplicatedChronicleMapHolder; import net.openhft.chronicle.map.impl.stage.data.DummyValueZeroData; import net.openhft.chronicle.map.impl.stage.query.ReplicatedMapQuery; import net.openhft.chronicle.map.impl.stage.replication.ReplicationUpdate; import net.openhft.chronicle.map.replication.MapRemoteQueryContext; import net.openhft.sg.StageRef; import net.openhft.sg.Staged; @Staged public abstract class ReplicatedInput<K, V, R> implements RemoteOperationContext<K>, MapRemoteQueryContext<K, V, R>, Replica.QueryContext<K, V> { @StageRef CheckOnEachPublicOperation checkOnEachPublicOperation; @StageRef ReplicatedChronicleMapHolder<K, V, R> mh; @StageRef ReplicationUpdate<K> ru; @StageRef ReplicatedMapQuery<K, V, ?> q; @StageRef SegmentStages s; @StageRef DummyValueZeroData<V> dummyValue; @Override public Data<V> dummyZeroValue() { checkOnEachPublicOperation.checkOnEachPublicOperation(); return dummyValue; } public void processReplicatedEvent(byte remoteNodeIdentifier, Bytes replicatedInputBytes) { long timestamp = replicatedInputBytes.readStopBit(); byte identifier = replicatedInputBytes.readByte(); ru.initReplicationUpdate(identifier, timestamp, remoteNodeIdentifier); boolean isDeleted = replicatedInputBytes.readBoolean(); long keySize = mh.m().keySizeMarshaller.readSize(replicatedInputBytes); long keyOffset = replicatedInputBytes.readPosition(); q.initInputKey(q.getInputKeyBytesAsData(replicatedInputBytes, keyOffset, keySize)); if (isDeleted) { s.innerUpdateLock.lock(); mh.m().remoteOperations.remove(this); } else { replicatedInputBytes.readSkip(keySize); long valueSize = mh.m().valueSizeMarshaller.readSize(replicatedInputBytes); long valueOffset = replicatedInputBytes.readPosition(); Data<V> value = q.wrapValueBytesAsData(replicatedInputBytes, valueOffset, valueSize); s.innerWriteLock.lock(); mh.m().remoteOperations.put(this, value); } } @Override public void remotePut( Data<V> newValue, byte remoteEntryIdentifier, long remoteEntryTimestamp, byte remoteNodeIdentifier) { ru.initReplicationUpdate(remoteEntryIdentifier, remoteEntryTimestamp, remoteNodeIdentifier); s.innerUpdateLock.lock(); mh.m().remoteOperations.put(this, newValue); } @Override public void remoteRemove( byte remoteEntryIdentifier, long remoteEntryTimestamp, byte remoteNodeIdentifier) { ru.initReplicationUpdate(remoteEntryIdentifier, remoteEntryTimestamp, remoteNodeIdentifier); s.innerWriteLock.lock(); mh.m().remoteOperations.remove(this); } }