package org.simantics.acorn.internal; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.simantics.acorn.ClusterManager; import org.simantics.acorn.exception.AcornAccessVerificationException; import org.simantics.acorn.exception.IllegalAcornStateException; import org.simantics.acorn.lru.ClusterChangeSet; import org.simantics.acorn.lru.ClusterStreamChunk; import org.simantics.acorn.lru.ClusterChangeSet.Entry; import org.simantics.acorn.lru.ClusterChangeSet.Type; import org.simantics.db.exception.DatabaseException; import org.simantics.db.service.ClusterUID; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class UndoClusterUpdateProcessor extends ClusterUpdateProcessorBase { private static final Logger LOGGER = LoggerFactory.getLogger(UndoClusterUpdateProcessor.class); public final static boolean DEBUG = false; final private ClusterChangeSet ccs; private int oldValuesIndex = 0; private int statementMaskIndex = 0; final public List entries = new ArrayList<>(); public UndoClusterUpdateProcessor(ClusterManager client, ClusterStreamChunk chunk, ClusterChangeSet ccs) throws DatabaseException { super(client, readOperation(client, chunk, ccs)); this.ccs = ccs; } private static byte[] readOperation(ClusterManager manager, ClusterStreamChunk chunk, ClusterChangeSet ccs) throws AcornAccessVerificationException, IllegalAcornStateException { chunk.makeResident(); return chunk.getOperation(ccs.chunkOffset); } @Override void create() throws DatabaseException { } @Override void delete(int ri) throws DatabaseException { byte[] old = ccs.oldValues.get(oldValuesIndex); boolean oldValueEx = ccs.oldValueEx.get(oldValuesIndex) > 0; oldValuesIndex++; if(old != null) { entries.add(new Entry(ri, oldValueEx, old, null)); } } @Override void modify(int resourceKey, long offset, int size, byte[] bytes, int pos) throws DatabaseException { } @Override void set(int resourceKey, byte[] bytes, int length) throws DatabaseException { byte[] old = ccs.oldValues.get(oldValuesIndex); boolean oldValueEx = ccs.oldValueEx.get(oldValuesIndex) > 0; oldValuesIndex++; entries.add(new Entry(resourceKey, oldValueEx, old, Arrays.copyOf(valueBuffer, length))); } @Override void claim(int resourceKey, int predicateKey, int objectKey, ClusterUID puid, ClusterUID ouid) throws DatabaseException { boolean add = ccs.statementMask.get(statementMaskIndex++) > 0; if(add) { entries.add(new Entry(Type.ADD, resourceKey, puid, predicateKey & 0xFFF, ouid, objectKey & 0xFFF)); } } @Override void deny(int resourceKey, int predicateKey, int objectKey, ClusterUID puid, ClusterUID ouid) throws DatabaseException { boolean remove = ccs.statementMask.get(statementMaskIndex++) > 0; if(remove) { entries.add(new Entry(Type.REMOVE, resourceKey, puid, predicateKey & 0xFFF, ouid, objectKey & 0xFFF)); } } @Override void setImmutable(boolean value) { LOGGER.error("Attempted to undo `setImmutable({})` cluster operation for cluster {} which is not supported.", value, ccs.cuid); } }