/* * 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.query; import net.openhft.chronicle.hash.Data; import net.openhft.chronicle.hash.replication.ReplicableEntry; import net.openhft.chronicle.map.impl.stage.data.DummyValueZeroData; import net.openhft.chronicle.map.impl.stage.entry.ReplicatedMapEntryStages; import net.openhft.chronicle.map.impl.stage.replication.ReplicationUpdate; import net.openhft.chronicle.map.replication.MapRemoteQueryContext; import net.openhft.chronicle.map.replication.MapReplicableEntry; import net.openhft.chronicle.set.replication.SetRemoteQueryContext; import net.openhft.chronicle.set.replication.SetReplicableEntry; import net.openhft.sg.StageRef; import net.openhft.sg.Staged; import org.jetbrains.annotations.Nullable; @Staged public abstract class ReplicatedMapQuery<K, V, R> extends MapQuery<K, V, R> implements MapRemoteQueryContext<K, V, R>, SetRemoteQueryContext<K, R>, ReplicableEntry, MapReplicableEntry<K, V>, SetReplicableEntry<K> { @StageRef ReplicatedMapEntryStages<K, V> e; @StageRef ReplicationUpdate ru; @StageRef ReplicatedMapAbsentDelegating<K, V> absentDelegating; @Nullable @Override public Absent<K, V> absentEntry() { checkOnEachPublicOperation.checkOnEachPublicOperation(); if (entryPresent()) { return null; } else { if (!ks.searchStatePresent()) { return absentDelegating; } else { assert e.entryDeleted(); return absent; } } } @Override public boolean entryPresent() { return super.entryPresent() && !e.entryDeleted(); } @StageRef DummyValueZeroData<V> dummyValue; @Override public ReplicatedMapQuery<K, V, R> entry() { checkOnEachPublicOperation.checkOnEachPublicOperation(); return entryPresent() ? this : null; } @Override public void doRemove() { checkOnEachPublicOperation.checkOnEachPublicOperation(); s.innerUpdateLock.lock(); if (entryPresent()) { if (e.valueSize > dummyValue.size()) e.innerDefaultReplaceValue(dummyValue); e.updatedReplicationStateOnPresentEntry(); e.writeEntryDeleted(); ru.updateChange(); s.tierDeleted(s.tierDeleted() + 1); } else { throw new IllegalStateException(mh.h().toIdentityString() + ": Entry is absent in the map when doRemove() is called"); } } @Override public void doRemoveCompletely() { boolean wasDeleted = e.entryDeleted(); super.doRemove(); ru.dropChange(); if (wasDeleted) s.tierDeleted(s.tierDeleted() - 1L); } @Override public void doReplaceValue(Data<V> newValue) { super.doReplaceValue(newValue); e.updatedReplicationStateOnPresentEntry(); ru.updateChange(); } }