Madan Jampani
Committed by Gerrit Code Review

Support for building a immutable ConsistentMap and DistributedSet

Change-Id: Ic34684551f5c7d1f4fdc4cd3fc1a7bfabc5681f5
......@@ -56,6 +56,15 @@ public interface ConsistentMapBuilder<K, V> {
public ConsistentMapBuilder<K, V> withPartitionsDisabled();
/**
* Disables map updates.
* <p>
* Attempt to update the built map will throw {@code UnsupportedOperationException}.
*
* @return this ConsistentMapBuilder
*/
public ConsistentMapBuilder<K, V> withUpdatesDisabled();
/**
* Builds an consistent map based on the configuration options
* supplied to this builder.
*
......
......@@ -53,6 +53,15 @@ public interface SetBuilder<E> {
public SetBuilder<E> withSerializer(Serializer serializer);
/**
* Disables set updates.
* <p>
* Attempt to update the built set will throw {@code UnsupportedOperationException}.
*
* @return this SetBuilder
*/
SetBuilder<E> withUpdatesDisabled();
/**
* Builds an set based on the configuration options
* supplied to this builder.
*
......
......@@ -48,6 +48,7 @@ public class DefaultAsyncConsistentMap<K, V> implements AsyncConsistentMap<K, V>
private final String name;
private final Database database;
private final Serializer serializer;
private final boolean readOnly;
private static final String ERROR_NULL_KEY = "Key cannot be null";
private static final String ERROR_NULL_VALUE = "Null values are not allowed";
......@@ -68,10 +69,12 @@ public class DefaultAsyncConsistentMap<K, V> implements AsyncConsistentMap<K, V>
public DefaultAsyncConsistentMap(String name,
Database database,
Serializer serializer) {
Serializer serializer,
boolean readOnly) {
this.name = checkNotNull(name, "map name cannot be null");
this.database = checkNotNull(database, "database cannot be null");
this.serializer = checkNotNull(serializer, "serializer cannot be null");
this.readOnly = readOnly;
}
@Override
......@@ -108,6 +111,7 @@ public class DefaultAsyncConsistentMap<K, V> implements AsyncConsistentMap<K, V>
public CompletableFuture<Versioned<V>> put(K key, V value) {
checkNotNull(key, ERROR_NULL_KEY);
checkNotNull(value, ERROR_NULL_VALUE);
checkIfUnmodifiable();
return database.put(name, keyCache.getUnchecked(key), serializer.encode(value))
.thenApply(this::unwrapResult)
.thenApply(v -> v != null
......@@ -117,6 +121,7 @@ public class DefaultAsyncConsistentMap<K, V> implements AsyncConsistentMap<K, V>
@Override
public CompletableFuture<Versioned<V>> remove(K key) {
checkNotNull(key, ERROR_NULL_KEY);
checkIfUnmodifiable();
return database.remove(name, keyCache.getUnchecked(key))
.thenApply(this::unwrapResult)
.thenApply(v -> v != null
......@@ -125,6 +130,7 @@ public class DefaultAsyncConsistentMap<K, V> implements AsyncConsistentMap<K, V>
@Override
public CompletableFuture<Void> clear() {
checkIfUnmodifiable();
return database.clear(name).thenApply(this::unwrapResult);
}
......@@ -157,6 +163,7 @@ public class DefaultAsyncConsistentMap<K, V> implements AsyncConsistentMap<K, V>
public CompletableFuture<Versioned<V>> putIfAbsent(K key, V value) {
checkNotNull(key, ERROR_NULL_KEY);
checkNotNull(value, ERROR_NULL_VALUE);
checkIfUnmodifiable();
return database.putIfAbsent(name,
keyCache.getUnchecked(key),
serializer.encode(value))
......@@ -169,6 +176,7 @@ public class DefaultAsyncConsistentMap<K, V> implements AsyncConsistentMap<K, V>
public CompletableFuture<Boolean> remove(K key, V value) {
checkNotNull(key, ERROR_NULL_KEY);
checkNotNull(value, ERROR_NULL_VALUE);
checkIfUnmodifiable();
return database.remove(name, keyCache.getUnchecked(key), serializer.encode(value))
.thenApply(this::unwrapResult);
}
......@@ -176,6 +184,7 @@ public class DefaultAsyncConsistentMap<K, V> implements AsyncConsistentMap<K, V>
@Override
public CompletableFuture<Boolean> remove(K key, long version) {
checkNotNull(key, ERROR_NULL_KEY);
checkIfUnmodifiable();
return database.remove(name, keyCache.getUnchecked(key), version)
.thenApply(this::unwrapResult);
......@@ -185,6 +194,7 @@ public class DefaultAsyncConsistentMap<K, V> implements AsyncConsistentMap<K, V>
public CompletableFuture<Boolean> replace(K key, V oldValue, V newValue) {
checkNotNull(key, ERROR_NULL_KEY);
checkNotNull(newValue, ERROR_NULL_VALUE);
checkIfUnmodifiable();
byte[] existing = oldValue != null ? serializer.encode(oldValue) : null;
return database.replace(name, keyCache.getUnchecked(key), existing, serializer.encode(newValue))
.thenApply(this::unwrapResult);
......@@ -194,6 +204,7 @@ public class DefaultAsyncConsistentMap<K, V> implements AsyncConsistentMap<K, V>
public CompletableFuture<Boolean> replace(K key, long oldVersion, V newValue) {
checkNotNull(key, ERROR_NULL_KEY);
checkNotNull(newValue, ERROR_NULL_VALUE);
checkIfUnmodifiable();
return database.replace(name, keyCache.getUnchecked(key), oldVersion, serializer.encode(newValue))
.thenApply(this::unwrapResult);
}
......@@ -216,4 +227,10 @@ public class DefaultAsyncConsistentMap<K, V> implements AsyncConsistentMap<K, V>
throw new IllegalStateException("Must not be here");
}
}
private void checkIfUnmodifiable() {
if (readOnly) {
throw new UnsupportedOperationException();
}
}
}
\ No newline at end of file
......
......@@ -45,8 +45,9 @@ public class DefaultConsistentMap<K, V> implements ConsistentMap<K, V> {
public DefaultConsistentMap(String name,
Database database,
Serializer serializer) {
asyncMap = new DefaultAsyncConsistentMap<>(name, database, serializer);
Serializer serializer,
boolean readOnly) {
asyncMap = new DefaultAsyncConsistentMap<>(name, database, serializer, readOnly);
}
@Override
......
......@@ -19,6 +19,7 @@ public class DefaultConsistentMapBuilder<K, V> implements ConsistentMapBuilder<K
private Serializer serializer;
private String name;
private boolean partitionsEnabled = true;
private boolean readOnly = false;
private final Database partitionedDatabase;
private final Database inMemoryDatabase;
......@@ -47,6 +48,12 @@ public class DefaultConsistentMapBuilder<K, V> implements ConsistentMapBuilder<K
return this;
}
@Override
public ConsistentMapBuilder<K, V> withUpdatesDisabled() {
readOnly = true;
return this;
}
private boolean validInputs() {
return name != null && serializer != null;
}
......@@ -57,7 +64,8 @@ public class DefaultConsistentMapBuilder<K, V> implements ConsistentMapBuilder<K
return new DefaultConsistentMap<>(
name,
partitionsEnabled ? partitionedDatabase : inMemoryDatabase,
serializer);
serializer,
readOnly);
}
@Override
......@@ -66,6 +74,7 @@ public class DefaultConsistentMapBuilder<K, V> implements ConsistentMapBuilder<K
return new DefaultAsyncConsistentMap<>(
name,
partitionsEnabled ? partitionedDatabase : inMemoryDatabase,
serializer);
serializer,
readOnly);
}
}
\ No newline at end of file
......
......@@ -33,8 +33,8 @@ public class DefaultDistributedSet<E> implements Set<E> {
private final ConsistentMap<E, Boolean> backingMap;
public DefaultDistributedSet(String name, Database database, Serializer serializer) {
backingMap = new DefaultConsistentMap<>(name, database, serializer);
public DefaultDistributedSet(String name, Database database, Serializer serializer, boolean readOnly) {
backingMap = new DefaultConsistentMap<>(name, database, serializer, readOnly);
}
@Override
......
......@@ -34,6 +34,7 @@ public class DefaultSetBuilder<E> implements SetBuilder<E> {
private Serializer serializer;
private String name;
private final Database database;
private boolean readOnly;
public DefaultSetBuilder(Database database) {
this.database = checkNotNull(database);
......@@ -53,6 +54,12 @@ public class DefaultSetBuilder<E> implements SetBuilder<E> {
return this;
}
@Override
public SetBuilder<E> withUpdatesDisabled() {
readOnly = true;
return this;
}
private boolean validInputs() {
return name != null && serializer != null;
}
......@@ -60,6 +67,6 @@ public class DefaultSetBuilder<E> implements SetBuilder<E> {
@Override
public Set<E> build() {
checkState(validInputs());
return new DefaultDistributedSet<>(name, database, serializer);
return new DefaultDistributedSet<>(name, database, serializer, readOnly);
}
}
......
......@@ -72,7 +72,7 @@ public class DefaultTransactionContext implements TransactionContext {
checkNotNull(serializer);
return txMaps.computeIfAbsent(mapName, name -> new DefaultTransactionalMap<>(
name,
new DefaultConsistentMap<>(name, database, serializer),
new DefaultConsistentMap<>(name, database, serializer, false),
this,
serializer));
}
......@@ -99,4 +99,4 @@ public class DefaultTransactionContext implements TransactionContext {
checkState(isOpen, TX_NOT_OPEN_ERROR);
txMaps.values().forEach(m -> m.rollback());
}
}
\ No newline at end of file
}
......
......@@ -60,7 +60,7 @@ public class TransactionManager {
*/
public TransactionManager(Database database) {
this.database = checkNotNull(database, "database cannot be null");
this.transactions = new DefaultAsyncConsistentMap<>("onos-transactions", this.database, serializer);
this.transactions = new DefaultAsyncConsistentMap<>("onos-transactions", this.database, serializer, false);
}
/**
......@@ -121,4 +121,4 @@ public class TransactionManager {
transaction.transition(Transaction.State.ROLLEDBACK)))
.thenApply(v -> true);
}
}
\ No newline at end of file
}
......