class ReplicatedMapEntryStages<K, V> extends MapEntryStages<K, V>
        implements MapReplicableEntry<K, V> {

    @StageRef
    ReplicatedChronicleMapHolder<?, ?, ?> mh;
    @StageRef
    ReplicationUpdate ru;

    @Stage("ReplicationState")
    long replicationBytesOffset = -1;

    void initReplicationState() {
        replicationBytesOffset = keyEnd();
    }

    void updateReplicationState(byte identifier, long timestamp) {
        initDelayedUpdateChecksum(true);
        Bytes segmentBytes = s.segmentBytesForWrite();
        segmentBytes.writePosition(replicationBytesOffset);
        segmentBytes.writeLong(timestamp);
        segmentBytes.writeByte(identifier);
    }

    private long timestampOffset() {
        return replicationBytesOffset;
    }

    public long timestamp() {
        return s.segmentBS.readLong(replicationBytesOffset);
    }

    private long identifierOffset() {
        return replicationBytesOffset + 8L;
    }

    byte identifier() {
        return s.segmentBS.readByte(identifierOffset());
    }

    private long entryDeletedOffset() {
        return replicationBytesOffset + 9L;
    }

    @Override
    public boolean entryDeleted() {
        return s.segmentBS.readBoolean(entryDeletedOffset());
    }

    public void writeEntryPresent() {
        s.segmentBS.writeBoolean(entryDeletedOffset(), false);
    }

    public void writeEntryDeleted() {
        s.segmentBS.writeBoolean(entryDeletedOffset(), true);
    }

    @Override
    public byte originIdentifier() {
        checkOnEachPublicOperation.checkOnEachPublicOperation();
        return identifier();
    }

    @Override
    public long originTimestamp() {
        checkOnEachPublicOperation.checkOnEachPublicOperation();
        return timestamp();
    }

    @Override
    long countValueSizeOffset() {
        return super.countValueSizeOffset() + ADDITIONAL_ENTRY_BYTES;
    }

    @Override
    public void updateOrigin(byte newIdentifier, long newTimestamp) {
        checkOnEachPublicOperation.checkOnEachPublicOperation();
        s.innerWriteLock.lock();
        updateReplicationState(newIdentifier, newTimestamp);
    }

    @Override
    public void dropChanged() {
        checkOnEachPublicOperation.checkOnEachPublicOperation();
        s.innerUpdateLock.lock();
        ru.dropChange();
    }

    @Override
    public void dropChangedFor(byte remoteIdentifier) {
        checkOnEachPublicOperation.checkOnEachPublicOperation();
        s.innerUpdateLock.lock();
        ru.dropChangeFor(remoteIdentifier);
    }

    @Override
    public void raiseChanged() {
        checkOnEachPublicOperation.checkOnEachPublicOperation();
        s.innerUpdateLock.lock();
        ru.raiseChange();
    }

    @Override
    public void raiseChangedFor(byte remoteIdentifier) {
        checkOnEachPublicOperation.checkOnEachPublicOperation();
        s.innerUpdateLock.lock();
        ru.raiseChangeFor(remoteIdentifier);
    }

    @Override
    public void raiseChangedForAllExcept(byte remoteIdentifier) {
        checkOnEachPublicOperation.checkOnEachPublicOperation();
        s.innerUpdateLock.lock();
        ru.raiseChangeForAllExcept(remoteIdentifier);
    }

    @Override
    public boolean isChanged() {
        checkOnEachPublicOperation.checkOnEachPublicOperation();
        s.innerReadLock.lock();
        return ru.changed();
    }

    public void updatedReplicationStateOnPresentEntry() {<FILL_FUNCTION_BODY>}

    public void updatedReplicationStateOnAbsentEntry() {
        if (!ru.replicationUpdateInit()) {
            s.innerWriteLock.lock();
            updateReplicationState(mh.m().identifier(), currentTime());
        }
    }

    @Override
    protected void relocation(Data<V> newValue, long newEntrySize) {
        long oldPos = pos;
        long oldTierIndex = s.tierIndex;
        super.relocation(newValue, newEntrySize);
        ru.moveChange(oldTierIndex, oldPos, pos);
    }

    @Override
    long sizeOfEverythingBeforeValue(long keySize, long valueSize) {
        return super.sizeOfEverythingBeforeValue(keySize, valueSize) + ADDITIONAL_ENTRY_BYTES;
    }
}

        if (!ru.replicationUpdateInit()) {
            s.innerWriteLock.lock();
            long timestamp = Math.max(timestamp() + 1, currentTime());
            updateReplicationState(mh.m().identifier(), timestamp);
        }
    
<methods>public non-sealed void <init>() ,public boolean entryDeleted() ,public long entryEnd() ,public final long entrySize(long, long) ,public final void freeExtraAllocatedChunks() ,public void initValue(Data<?>) ,public void innerDefaultReplaceValue(Data<V>) ,public long innerEntrySize(long, long) ,public long newEntrySize(Data<V>, long, long) ,public long newSizeOfEverythingBeforeValue(Data<V>) ,public Data<V> value() ,public void writeValue(Data<?>) <variables>public net.openhft.chronicle.hash.impl.stage.entry.AllocatedChunks allocatedChunks,public EntryValueBytesData<V> entryValue,KeySearch<K> ks,public VanillaChronicleMapHolder<?,?,?> mh,public long valueOffset,public long valueSize,public long valueSizeOffset