package io.qdb.kvstore; import java.io.File; import java.io.IOException; import java.util.HashMap; import java.util.Map; /** * Helps create a DataStore instance. This makes it possible for the data store to receive all its configuration * in the constructor without breaking clients when new parameters are added. */ public class KeyValueStoreBuilder<K, V> { private File dir; private KeyValueStoreSerializer serializer; private KeyValueStore.VersionProvider<V> versionProvider; private KeyValueStore.Listener<K, V> listener; private int txLogSizeM = 10; private int maxObjectSize = 100000; private int snapshotCount = 3; private int snapshotIntervalSecs = 60; private Map<String, Class> aliases = new HashMap<String, Class>(); public KeyValueStoreBuilder() { } public KeyValueStore<K, V> create() throws IOException { if (dir == null) throw new IllegalStateException("dir is required"); if (serializer == null) serializer = new GensonSerializer(aliases); if (versionProvider == null) versionProvider = new NopVersionProvider<V>(); return new KeyValueStoreImpl<K, V>(serializer, versionProvider, listener, dir, txLogSizeM, maxObjectSize, snapshotCount, snapshotIntervalSecs); } /** * Directory for snapshots and the transaction log. Created if it does not exist. Must be writable. */ public KeyValueStoreBuilder dir(File dir) { this.dir = dir; return this; } /** * Directory for snapshots and the transaction log. Created if it does not exist. Must be writable. */ public KeyValueStoreBuilder dir(String dir) { this.dir = new File(dir); return this; } /** * The serializer is responsible for converting objects to/from byte streams. The default serializer stores * data as JSON. * @see #alias(String, Class) */ public KeyValueStoreBuilder serializer(KeyValueStoreSerializer serializer) { this.serializer = serializer; return this; } /** * The default serializer includes the fully qualified name of each class in the JSON as a "@class" attribute. * Use this method to change what is stored for your classes e.g. addAlias(Foo.class, "foo") will store Foo * instances as "@class": "foo" instead of "@class": "com.acme.Foo". Note that if you supply your own serializer * aliases are ignored. */ public KeyValueStoreBuilder alias(String alias, Class<?> forClass) { aliases.put(alias, forClass); return this; } /** * If you want to use optimistic locking then you must supply a version provider which is responsible for * getting and incrementing version numbers. */ public KeyValueStoreBuilder versionProvider(KeyValueStore.VersionProvider<V> versionProvider) { this.versionProvider = versionProvider; return this; } /** * If you want to be notified when the store is changed then supply a listener. */ public KeyValueStoreBuilder listener(KeyValueStore.Listener<K, V> listener) { this.listener = listener; return this; } /** * Set the max size in M of the transaction log. Default is 10M. */ public KeyValueStoreBuilder txLogSizeM(int txLogSizeM) { this.txLogSizeM = txLogSizeM; return this; } /** * Set the maximum size in bytes of stored objects. Default is 100000. */ public KeyValueStoreBuilder maxObjectSize(int maxObjectSize) { this.maxObjectSize = maxObjectSize; return this; } /** * How many snapshot files should be kept? Default is 3. */ public KeyValueStoreBuilder snapshotCount(int snapshotCount) { this.snapshotCount = snapshotCount; return this; } /** * How often should automatic snapshots be taken? Default is every 60 seconds if changes have been made to the * store. Snapshots are taken as quickly as possible if the transaction log is more than half full. */ public KeyValueStoreBuilder snapshotIntervalSecs(int snapshotIntervalSecs) { this.snapshotIntervalSecs = snapshotIntervalSecs; return this; } private static class NopVersionProvider<V> implements KeyValueStore.VersionProvider<V> { public Object getVersion(V value) { return null; } public void incVersion(V value) { } } }