本文次要钻研一下claudb的Database

Database

claudb-1.7.1/src/main/java/com/github/tonivade/claudb/data/Database.java

public interface Database {  int size();  boolean isEmpty();  boolean containsKey(DatabaseKey key);  DatabaseValue get(DatabaseKey key);  DatabaseValue put(DatabaseKey key, DatabaseValue value);  DatabaseValue remove(DatabaseKey key);  void clear();  ImmutableSet<DatabaseKey> keySet();  Sequence<DatabaseValue> values();  ImmutableSet<Tuple2<DatabaseKey, DatabaseValue>> entrySet();  default SafeString getString(SafeString key) {    return getOrDefault(safeKey(key), DatabaseValue.EMPTY_STRING).getString();  }  default ImmutableList<SafeString> getList(SafeString key) {    return getOrDefault(safeKey(key), DatabaseValue.EMPTY_LIST).getList();  }  default ImmutableSet<SafeString> getSet(SafeString key) {    return getOrDefault(safeKey(key), DatabaseValue.EMPTY_SET).getSet();  }  default NavigableSet<Entry<Double, SafeString>> getSortedSet(SafeString key) {    return getOrDefault(safeKey(key), DatabaseValue.EMPTY_ZSET).getSortedSet();  }  default ImmutableMap<SafeString, SafeString> getHash(SafeString key) {    return getOrDefault(safeKey(key), DatabaseValue.EMPTY_HASH).getHash();  }  default void putAll(ImmutableMap<? extends DatabaseKey, ? extends DatabaseValue> map) {    map.forEach(this::put);  }  default DatabaseValue putIfAbsent(DatabaseKey key, DatabaseValue value) {    DatabaseValue oldValue = get(key);    if (oldValue == null) {        oldValue = put(key, value);    }    return oldValue;  }  default DatabaseValue merge(DatabaseKey key, DatabaseValue value,      BiFunction<DatabaseValue, DatabaseValue, DatabaseValue> remappingFunction) {    DatabaseValue oldValue = get(key);    DatabaseValue newValue = oldValue == null ? value : remappingFunction.apply(oldValue, value);    if(newValue == null) {      remove(key);    } else {      put(key, newValue);    }    return newValue;  }  default DatabaseValue getOrDefault(DatabaseKey key, DatabaseValue defaultValue) {    DatabaseValue value = get(key);    return (value != null || containsKey(key)) ? value : defaultValue;  }  default boolean isType(DatabaseKey key, DataType type) {    DatabaseValue value = get(key);    return value != null ? value.getType() == type : true;  }  default boolean rename(DatabaseKey from, DatabaseKey to) {    DatabaseValue value = remove(from);    if (value != null) {      put(to, value);      return true;    }    return false;  }  default void overrideAll(ImmutableMap<DatabaseKey, DatabaseValue> value) {    clear();    putAll(value);  }  default ImmutableSet<DatabaseKey> evictableKeys(Instant now) {    return entrySet()        .filter(entry -> entry.get2().isExpired(now))        .map(Tuple2::get1);  }}
  • Database接口定义了size、isEmpty、containsKey、get、put、remove、clear、keySet、values、entrySet办法;同时还提供了getString、getList、getSet、getSortedSet、getHash、putAll、putIfAbsent、merge、getOrDefault、isType、rename、overrideAll、evictableKeys这几个default办法

OnHeapDatabase

claudb-1.7.1/src/main/java/com/github/tonivade/claudb/data/OnHeapDatabase.java

public class OnHeapDatabase implements Database {  private final Map<DatabaseKey, DatabaseValue> cache;  public OnHeapDatabase(Map<DatabaseKey, DatabaseValue> cache) {    this.cache = cache;  }  @Override  public int size() {    return cache.size();  }  @Override  public boolean isEmpty() {    return cache.isEmpty();  }  @Override  public boolean containsKey(DatabaseKey key) {    return cache.containsKey(key);  }  @Override  public DatabaseValue get(DatabaseKey key) {    DatabaseValue value = cache.get(key);    if (value != null) {      if (!value.isExpired(Instant.now())) {        return value;      }      cache.remove(key);    }    return null;  }  @Override  public DatabaseValue put(DatabaseKey key, DatabaseValue value) {    DatabaseValue oldValue = cache.remove(key);    cache.put(key, value);    return oldValue;  }  @Override  public DatabaseValue remove(DatabaseKey key) {    return cache.remove(key);  }  @Override  public void clear() {    cache.clear();  }  @Override  public ImmutableSet<DatabaseKey> keySet() {    return ImmutableSet.from(cache.keySet());  }  @Override  public Sequence<DatabaseValue> values() {    return ImmutableSet.from(cache.values());  }  @Override  public ImmutableSet<Tuple2<DatabaseKey, DatabaseValue>> entrySet() {    return ImmutableSet.from(cache.entrySet()).map(Tuple::from);  }}
  • OnHeapDatabase实现了Database接口,它应用Map构造作为cache;其get办法在取出value不为null时会判断该value是否过期,如果过期则移除该key,返回null;其put办法会先执行remove获取oldValue,在put进去新值,最初返回oldValue

OffHeapDatabase

claudb-1.7.1/src/main/java/com/github/tonivade/claudb/data/OffHeapDatabase.java

public class OffHeapDatabase implements Database {  private OHCache<DatabaseKey, DatabaseValue> cache;  public OffHeapDatabase(OHCache<DatabaseKey, DatabaseValue> cache) {    this.cache = cache;  }  @Override  public int size() {    return (int) cache.size();  }  @Override  public boolean isEmpty() {    return cache.size() == 0;  }  @Override  public boolean containsKey(DatabaseKey key) {    return cache.containsKey(key);  }  @Override  public DatabaseValue get(DatabaseKey key) {    DatabaseValue value = cache.get(key);    if (value != null) {      if (!value.isExpired(Instant.now())) {        return value;      }      cache.remove(key);    }    return null;  }  @Override  public DatabaseValue put(DatabaseKey key, DatabaseValue value) {    cache.put(key, value);    return value;  }  @Override  public DatabaseValue remove(DatabaseKey key) {    DatabaseValue value = get(key);    cache.remove(key);    return value;  }  @Override  public void clear() {    cache.clear();  }  @Override  public ImmutableSet<DatabaseKey> keySet() {    Set<DatabaseKey> keys = new HashSet<>();    try (CloseableIterator<DatabaseKey> iterator = cache.keyIterator()) {      while (iterator.hasNext()) {        keys.add(iterator.next());      }    } catch(IOException e) {      throw new UncheckedIOException(e);    }    return ImmutableSet.from(keys);  }  @Override  public Sequence<DatabaseValue> values() {    List<DatabaseValue> values = new LinkedList<>();    for (DatabaseKey key : keySet()) {      values.add(cache.get(key));    }    return ImmutableList.from(values);  }  @Override  public ImmutableSet<Tuple2<DatabaseKey, DatabaseValue>> entrySet() {    return keySet().map(key -> Tuple.of(key, get(key)));  }}
  • OffHeapDatabase实现了Database接口,它应用OHCache作为cache,其get办法在取出value不为null时会判断该value是否过期,如果过期则移除该key,返回null;其put办法间接往cache笼罩该key,返回的是新值

DatabaseFactory

claudb-1.7.1/src/main/java/com/github/tonivade/claudb/data/DatabaseFactory.java

public interface DatabaseFactory {  Database create(String name);  void clear();}
  • DatabaseFactory接口定义了create、clear办法

OnHeapDatabaseFactory

claudb-1.7.1/src/main/java/com/github/tonivade/claudb/data/OnHeapDatabaseFactory.java

public class OnHeapDatabaseFactory implements DatabaseFactory {  @Override  public Database create(String name) {    return new OnHeapDatabase(new HashMap<>());  }  @Override  public void clear() {    // nothing to clear  }}
  • OnHeapDatabaseFactory实现了DatabaseFactory接口,其create应用HashMap创立OnHeapDatabase

OffHeapDatabaseFactory

claudb-1.7.1/src/main/java/com/github/tonivade/claudb/data/OffHeapDatabaseFactory.java

public class OffHeapDatabaseFactory implements DatabaseFactory {  @Override  public Database create(String name) {    return new OffHeapDatabase(createCache());  }  private OHCache<DatabaseKey, DatabaseValue> createCache() {    return builder()        .eviction(Eviction.NONE)        .throwOOME(true)        .keySerializer(new FSTSerializer<>())        .valueSerializer(new FSTSerializer<>())        .build();  }  private OHCacheBuilder<DatabaseKey, DatabaseValue> builder() {    return OHCacheBuilder.newBuilder();  }  @Override  public void clear() {    // nothing to do  }  private static class FSTSerializer<E> implements CacheSerializer<E> {    private static final FSTConfiguration FST = FSTConfiguration.createDefaultConfiguration();    static {      FST.registerClass(DatabaseValue.class);      FST.registerClass(DatabaseKey.class);      FST.registerClass(SafeString.class);      FST.registerClass(SortedSet.class);    }    @Override    public void serialize(E value, ByteBuffer buf) {      byte[] array = FST.asByteArray(value);      buf.putInt(array.length);      buf.put(array);    }    @SuppressWarnings("unchecked")    @Override    public E deserialize(ByteBuffer buf) {      int length = buf.getInt();      byte[] array = new byte[length];      buf.get(array);      return (E) FST.asObject(array);    }    @Override    public int serializedSize(E value) {      return FST.asByteArray(value).length + Integer.BYTES;    }  }}
  • OffHeapDatabaseFactory实现了DatabaseFactory接口,其create办法创立的是OffHeapDatabase;其createCache办法应用OHCacheBuilder来结构OHCache,其eviction为NONE,其throwOOME为true;其keySerializer及valueSerializer均为FSTSerializer

小结

claudb提供了OnHeapDatabase、OffHeapDatabase两种实现,前者应用HashMap,后者应用OHCache

doc

  • Database