org.locationtech.geogig.storage.memory.HeapObjectDatabse.java Source code

Java tutorial

Introduction

Here is the source code for org.locationtech.geogig.storage.memory.HeapObjectDatabse.java

Source

/* Copyright (c) 2012-2014 Boundless and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Distribution License v1.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/org/documents/edl-v10.html
 *
 * Contributors:
 * Gabriel Roldan (Boundless) - initial implementation
 */
package org.locationtech.geogig.storage.memory;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ConcurrentMap;

import org.locationtech.geogig.api.ObjectId;
import org.locationtech.geogig.api.RevObject;
import org.locationtech.geogig.storage.AbstractObjectDatabase;
import org.locationtech.geogig.storage.BulkOpListener;
import org.locationtech.geogig.storage.ObjectDatabase;
import org.locationtech.geogig.storage.datastream.DataStreamSerializationFactoryV1;

import com.google.common.base.Preconditions;
import com.google.common.base.Throwables;
import com.google.common.collect.AbstractIterator;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.ning.compress.lzf.LZFInputStream;

/**
 * Provides an implementation of a GeoGig object database that utilizes the heap for the storage of
 * objects.
 * 
 * @see AbstractObjectDatabase
 */
public class HeapObjectDatabse extends AbstractObjectDatabase implements ObjectDatabase {

    private ConcurrentMap<ObjectId, byte[]> objects;

    private HeapConflictsDatabase conflicts;

    public HeapObjectDatabse() {
        super(DataStreamSerializationFactoryV1.INSTANCE);
    }

    /**
     * Closes the database.
     * 
     * @see org.locationtech.geogig.storage.ObjectDatabase#close()
     */
    @Override
    public void close() {
        if (objects != null) {
            objects.clear();
            objects = null;
            conflicts.close();
            conflicts = null;
        }
    }

    /**
     * @return true if the database is open, false otherwise
     */
    @Override
    public boolean isOpen() {
        return objects != null;
    }

    /**
     * Opens the database for use by GeoGig.
     */
    @Override
    public void open() {
        if (isOpen()) {
            return;
        }
        objects = Maps.newConcurrentMap();
        conflicts = new HeapConflictsDatabase();
    }

    @Override
    public HeapConflictsDatabase getConflictsDatabase() {
        return conflicts;
    }

    /**
     * Determines if the given {@link ObjectId} exists in the object database.
     * 
     * @param id the id to search for
     * @return true if the object exists, false otherwise
     */
    @Override
    public boolean exists(ObjectId id) {
        checkNotNull(id);
        checkState(isOpen(), "db is closed");
        return objects.containsKey(id);
    }

    /**
     * Deletes the object with the provided {@link ObjectId id} from the database.
     * 
     * @param objectId the id of the object to delete
     * @return true if the object was deleted, false if it was not found
     */
    @Override
    public boolean delete(ObjectId objectId) {
        checkNotNull(objectId);
        checkState(isOpen(), "db is closed");
        return objects.remove(objectId) != null;
    }

    @Override
    protected List<ObjectId> lookUpInternal(byte[] raw) {
        throw new UnsupportedOperationException("we override lookup directly");
    }

    /**
     * Searches the database for {@link ObjectId}s that match the given partial id.
     * 
     * @param partialId the partial id to search for
     * @return a list of matching results
     */
    @Override
    public List<ObjectId> lookUp(final String partialId) {
        checkState(isOpen(), "db is closed");
        Preconditions.checkNotNull(partialId);
        List<ObjectId> matches = Lists.newLinkedList();
        for (ObjectId id : objects.keySet()) {
            if (id.toString().startsWith(partialId)) {
                matches.add(id);
            }
        }
        return matches;
    }

    @Override
    protected InputStream getRawInternal(ObjectId id, boolean failIfNotFound) throws IllegalArgumentException {

        byte[] data = objects.get(id);
        if (data == null) {
            if (failIfNotFound) {
                throw new IllegalArgumentException(id + " does not exist");
            }
            return null;
        }
        return new ByteArrayInputStream(data);
    }

    @Override
    protected boolean putInternal(ObjectId id, byte[] rawData) {
        byte[] previousValue = objects.putIfAbsent(id, rawData);
        return previousValue == null;
    }

    @Override
    public long deleteAll(Iterator<ObjectId> ids, final BulkOpListener listener) {
        checkState(isOpen(), "db is closed");
        long count = 0;
        while (ids.hasNext()) {
            ObjectId id = ids.next();
            byte[] removed = this.objects.remove(id);
            if (removed != null) {
                count++;
                listener.deleted(id);
            } else {
                listener.notFound(id);
            }
        }
        return count;
    }

    @Override
    public Iterator<RevObject> getAll(final Iterable<ObjectId> ids, final BulkOpListener listener) {
        checkState(isOpen(), "db is closed");

        final Iterator<ObjectId> iterator = Lists.newArrayList(ids).iterator();
        return new AbstractIterator<RevObject>() {

            @Override
            protected RevObject computeNext() {
                RevObject found = null;
                ObjectId id;
                byte[] raw;
                while (iterator.hasNext() && found == null) {
                    id = iterator.next();
                    raw = objects.get(id);
                    if (raw != null) {
                        try {
                            found = serializer.read(id, new LZFInputStream(new ByteArrayInputStream(raw)));
                        } catch (IOException e) {
                            throw Throwables.propagate(e);
                        }
                        listener.found(found.getId(), raw.length);
                    } else {
                        listener.notFound(id);
                    }
                }
                return found == null ? endOfData() : found;
            }
        };
    }

    @Override
    public void configure() {
        // No-op
    }

    @Override
    public void checkConfig() {
        // No-op
    }

    @Override
    public String toString() {
        return getClass().getSimpleName();
    }

}