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

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

The 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 org.jsimpledb.util.ByteReader;
import org.jsimpledb.util.ByteUtil;
import org.jsimpledb.util.ByteWriter;
import org.jsimpledb.util.CloseableIterator;

/**
 * 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 java.util.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, ByteUtil.getNextKey(key)); if (pair == null) return null; assert Arrays.equals(pair.getKey(), key); return pair.getValue(); } @Override public KVPair getAtLeast(byte[] minKey, byte[] maxKey) { if (minKey != null && maxKey != null && ByteUtil.compare(minKey, maxKey) >= 0) return null; try (final CloseableIterator i = this.getRange(minKey, maxKey, false)) { return i.hasNext() ? i.next() : null; } } @Override public KVPair getAtMost(byte[] maxKey, byte[] minKey) { if (minKey != null && maxKey != null && ByteUtil.compare(minKey, maxKey) >= 0) return null; try (final CloseableIterator i = this.getRange(minKey, maxKey, true)) { return i.hasNext() ? i.next() : null; } } @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) { try (final CloseableIterator i = this.getRange(minKey, maxKey, false)) { while (i.hasNext()) { i.next(); i.remove(); } } } @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; final long oldValue; try { oldValue = this.decodeCounter(previous); } catch (IllegalArgumentException e) { return; // if previous value is not valid, behavior is undefined } this.put(key, this.encodeCounter(oldValue + amount)); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy