All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jsimpledb.kv.AbstractKVStore Maven / Gradle / Ivy

There is a newer version: 3.6.1
Show newest version

/*
 * Copyright (C) 2015 Archie L. Cobbs. All rights reserved.
 */

package org.jsimpledb.kv;

import com.google.common.base.Preconditions;

import java.util.Arrays;
import java.util.Iterator;

import org.jsimpledb.util.ByteReader;
import org.jsimpledb.util.ByteUtil;
import org.jsimpledb.util.ByteWriter;

/**
 * Support superclass for {@link KVStore} implementations.
 *
 * 

* This class provides a partial implementation via the following methods: *

    *
  • A {@link #get get()} implementation based on {@link #getAtLeast getAtLeast()}
  • *
  • {@link #getAtLeast getAtLeast()} and {@link #getAtMost getAtMost()} implementations based on * {@link #getRange getRange()}.
  • *
  • A {@link #remove remove()} implementation that delegates to {@link #removeRange removeRange()}.
  • *
  • A {@link #removeRange removeRange()} implementation that delegates to {@link #getRange getRange()}, * iterating through the range of keys and removing them one-by-one via {@link Iterator#remove}.
  • *
  • {@link #encodeCounter encodeCounter()}, {@link #decodeCounter encodeCounter()}, and * {@link #adjustCounter adjustCounter()} implementations using normal reads and writes * of values in big-endian encoding (does not provide any lock-free behavior).
  • *
  • A {@link #put put()} implementation throwing {@link UnsupportedOperationException}
  • *
* *

* Therefore, a read-only {@link KVStore} implementation is possible simply by implementing {@link #getRange}. * * @see KVPairIterator */ public abstract class AbstractKVStore implements KVStore { protected AbstractKVStore() { } @Override public byte[] get(byte[] key) { final KVPair pair = this.getAtLeast(key); return pair != null && Arrays.equals(pair.getKey(), key) ? pair.getValue() : null; } @Override public KVPair getAtLeast(byte[] minKey) { final Iterator i = this.getRange(minKey, null, false); try { return i.hasNext() ? i.next() : null; } finally { this.closeIfPossible(i); } } @Override public KVPair getAtMost(byte[] maxKey) { final Iterator i = this.getRange(null, maxKey, true); try { return i.hasNext() ? i.next() : null; } finally { this.closeIfPossible(i); } } @Override public void put(byte[] key, byte[] value) { throw new UnsupportedOperationException(); } @Override public void remove(byte[] key) { this.removeRange(key, ByteUtil.getNextKey(key)); } @Override public void removeRange(byte[] minKey, byte[] maxKey) { final Iterator i = this.getRange(minKey, maxKey, false); try { while (i.hasNext()) { i.next(); i.remove(); } } finally { this.closeIfPossible(i); } } @Override public byte[] encodeCounter(long value) { final ByteWriter writer = new ByteWriter(8); ByteUtil.writeLong(writer, value); return writer.getBytes(); } @Override public long decodeCounter(byte[] value) { Preconditions.checkArgument(value.length == 8, "invalid encoded counter value length != 8"); return ByteUtil.readLong(new ByteReader(value)); } @Override public void adjustCounter(byte[] key, long amount) { if (key == null) throw new NullPointerException("null key"); final byte[] previous = this.get(key); if (previous == null) return; this.put(key, this.encodeCounter(this.decodeCounter(previous) + amount)); } private void closeIfPossible(Iterator i) { if (i instanceof AutoCloseable) { try { ((AutoCloseable)i).close(); } catch (Exception e) { // ignore } } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy