package org.mapdb;

import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Store which keeps all instances on heap. It does not use serialization.
 */

public class StoreHeap extends Store{

    protected final LongObjectMap[] data;
    protected final LongObjectMap[] rollback;

    protected static final Object TOMBSTONE = new Object();
    protected static final Object NULL = new Object();

    protected long[] freeRecid;
    protected int freeRecidTail;
    protected long maxRecid = RECID_FIRST;
    protected final Lock newRecidLock;
    protected List snapshots;


    public StoreHeap(boolean txDisabled, int lockScale, int lockingStrategy, boolean snapshotEnable){
        super(null,null,null,lockScale, 0, false,false,null,false,snapshotEnable,false, null);
        data = new LongObjectMap[this.lockScale];
        for(int i=0;i():
                null;

        for(long recid=1;recid<=RECID_LAST_RESERVED;recid++){
            data[lockPos(recid)].put(recid,NULL);
        }
    }


    @Override
    protected  A get2(long recid, Serializer serializer) {
        if(CC.ASSERT)
            assertReadLocked(recid);

        int pos = lockPos(recid);
        A ret =  (A) data[pos].get(recid);
        if(ret == null)
            throw new DBException.EngineGetVoid();
        if(ret == TOMBSTONE||ret==NULL)
            ret = null;
        return ret;
    }

    @Override
    public  void update(long recid, A value, Serializer serializer) {
        if(serializer==null)
            throw new NullPointerException();
        if(closed)
            throw new IllegalAccessError("closed");

        Object val2 = value==null?NULL:value;

        int pos = lockPos(recid);
        LongObjectMap data2 = data[pos];
        Lock lock = locks[pos].writeLock();
        lock.lock();
        try{
            Object old = data2.put(recid,val2);
            updateOld(pos, recid, old);
        }finally {
            lock.unlock();
        }
    }

    @Override
    protected void update2(long recid, DataIO.DataOutputByteArray out) {
        throw new UnsupportedOperationException();
    }

    @Override
    protected  void delete2(long recid, Serializer serializer) {
        int pos = lockPos(recid);

        if(CC.ASSERT)
            assertWriteLocked(pos);

        Object old = data[pos].put(recid,TOMBSTONE);
        updateOld(pos,recid,old);
    }

    @Override
    public  boolean compareAndSwap(long recid, A expectedOldValue, A newValue, Serializer serializer) {
        if(serializer==null)
            throw new NullPointerException();
        if(closed)
            throw new IllegalAccessError("closed");

        final int pos = lockPos(recid);
        final Lock lock = locks[pos].writeLock();
        lock.lock();
        try{
            A oldVal = get2(recid, serializer);
            if(oldVal==expectedOldValue || (oldVal!=null && serializer.equals(oldVal,expectedOldValue))){
                Object newValue2 = newValue==null?NULL:newValue;
                Object old = data[pos].put(recid, newValue2);

                updateOld(pos, recid, old);


                return true;
            }
            return false;
        }finally {
            lock.unlock();
        }
    }

    protected void updateOld(int pos, long recid, Object old) {
        if(rollback!=null){
            LongObjectMap rol = rollback[pos];
            if(rol.get(recid)==null)
                rol.put(recid,old);
        }
        if(snapshots!=null){
            for(Snapshot snap:snapshots){
                snap.oldData[pos].putIfAbsent(recid, old);
            }
        }
    }

    @Override
    public long getCurrSize() {
        return -1;
    }

    @Override
    public long getFreeSize() {
        return -1;
    }

    @Override
    public boolean fileLoad() {
        return false;
    }


    @Override
    public void backup(OutputStream out, boolean incremental) {
        //TODO full backup
        throw new UnsupportedOperationException("not yet implemented");
    }

    @Override
    public void backupRestore(InputStream[] in) {
        //TODO full backup
        throw new UnsupportedOperationException("not yet implemented");
    }

    @Override
    public long preallocate() {
        if(closed)
            throw new IllegalAccessError("closed");

        long recid = allocateRecid();
        int lockPos = lockPos(recid);
        Lock lock = locks[lockPos].writeLock();
        lock.lock();
        try{
            data[lockPos].put(recid,NULL);

            if(rollback!=null){
                LongObjectMap rol = rollback[lockPos];
                if(rol.get(recid)==null)
                    rol.put(recid,TOMBSTONE);
            }

        }finally {
            lock.unlock();
        }
        return recid;
    }

    protected long allocateRecid() {
        long recid;
        newRecidLock.lock();
        try {
            if(freeRecidTail>0) {
                //take from stack of free recids
                freeRecidTail--;
                recid = freeRecid[freeRecidTail];
                freeRecid[freeRecidTail]=0;
            }else{
                //allocate new recid
                recid = maxRecid++;
            }

        }finally {
            newRecidLock.unlock();
        }
        return recid;
    }

    @Override
    public  long put(A value, Serializer serializer) {
        if(closed)
            throw new IllegalAccessError("closed");

        long recid = allocateRecid();
        update(recid, value, serializer);
        return recid;
    }

    @Override
    public void close() {
        closed = true;
    }

    @Override
    public void commit() {
        if(closed)
            throw new IllegalAccessError("closed");

        if(rollback!=null) {
            commitLock.lock();
            try {
                for (int i = 0; i < data.length; i++) {
                    Lock lock = locks[i].writeLock();
                    lock.lock();
                    try {
                        rollback[i].clear();
                    }finally {
                        lock.unlock();
                    }
                }
            } finally {
                commitLock.unlock();
            }
        }
    }

    @Override
    public void rollback() throws UnsupportedOperationException {
        if(closed)
            throw new IllegalAccessError("closed");

        if(rollback==null)
            throw new UnsupportedOperationException();

        commitLock.lock();
        try{
            for (int i = 0; i < data.length; i++) {
                Lock lock = locks[i].writeLock();
                lock.lock();
                try {
                    //move content of rollback map into primary map
                    LongObjectMap r = rollback[i];
                    LongObjectMap d = data[i];

                    long[] rs = r.set;
                    Object[] rv = r.values;
                    for(int j=0;j A get(long recid, Serializer serializer) {
            StoreHeap engine = this.engine;
            int pos = engine.lockPos(recid);
            Lock lock = engine.locks[pos].readLock();
            lock.lock();
            try{
                Object ret = oldData[pos].get(recid);
                if(ret==null)
                    ret = engine.get(recid,serializer);
                if(ret==TOMBSTONE)
                    return null;
                return (A) ret;
            }finally {
                lock.unlock();
            }
        }

        @Override
        public void close() {
            engine.snapshots.remove(Snapshot.this);
            engine = null;
            oldData = null;
        }

        @Override
        public boolean isClosed() {
            return engine!=null;
        }

        @Override
        public boolean canRollback() {
            return false;
        }

        @Override
        public boolean canSnapshot() {
            return true;
        }

        @Override
        public Engine snapshot() throws UnsupportedOperationException {
            return this;
        }

        @Override
        public Engine getWrappedEngine() {
            return engine;
        }

        @Override
        public void clearCache() {

        }
    }
}

 

Ads help maintain this website.