Support for building a immutable ConsistentMap and DistributedSet

Change-Id: Ic34684551f5c7d1f4fdc4cd3fc1a7bfabc5681f5
This commit is contained in:
Madan Jampani 2015-05-01 13:01:20 -07:00 committed by Gerrit Code Review
parent e114f04812
commit 02b7fb8b1a
9 changed files with 64 additions and 12 deletions

View File

@ -55,6 +55,15 @@ public interface ConsistentMapBuilder<K, V> {
*/ */
public ConsistentMapBuilder<K, V> withPartitionsDisabled(); 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 * Builds an consistent map based on the configuration options
* supplied to this builder. * supplied to this builder.

View File

@ -52,6 +52,15 @@ public interface SetBuilder<E> {
*/ */
public SetBuilder<E> withSerializer(Serializer serializer); 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 * Builds an set based on the configuration options
* supplied to this builder. * supplied to this builder.

View File

@ -48,6 +48,7 @@ public class DefaultAsyncConsistentMap<K, V> implements AsyncConsistentMap<K, V>
private final String name; private final String name;
private final Database database; private final Database database;
private final Serializer serializer; 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_KEY = "Key cannot be null";
private static final String ERROR_NULL_VALUE = "Null values are not allowed"; 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, public DefaultAsyncConsistentMap(String name,
Database database, Database database,
Serializer serializer) { Serializer serializer,
boolean readOnly) {
this.name = checkNotNull(name, "map name cannot be null"); this.name = checkNotNull(name, "map name cannot be null");
this.database = checkNotNull(database, "database cannot be null"); this.database = checkNotNull(database, "database cannot be null");
this.serializer = checkNotNull(serializer, "serializer cannot be null"); this.serializer = checkNotNull(serializer, "serializer cannot be null");
this.readOnly = readOnly;
} }
@Override @Override
@ -108,6 +111,7 @@ public class DefaultAsyncConsistentMap<K, V> implements AsyncConsistentMap<K, V>
public CompletableFuture<Versioned<V>> put(K key, V value) { public CompletableFuture<Versioned<V>> put(K key, V value) {
checkNotNull(key, ERROR_NULL_KEY); checkNotNull(key, ERROR_NULL_KEY);
checkNotNull(value, ERROR_NULL_VALUE); checkNotNull(value, ERROR_NULL_VALUE);
checkIfUnmodifiable();
return database.put(name, keyCache.getUnchecked(key), serializer.encode(value)) return database.put(name, keyCache.getUnchecked(key), serializer.encode(value))
.thenApply(this::unwrapResult) .thenApply(this::unwrapResult)
.thenApply(v -> v != null .thenApply(v -> v != null
@ -117,6 +121,7 @@ public class DefaultAsyncConsistentMap<K, V> implements AsyncConsistentMap<K, V>
@Override @Override
public CompletableFuture<Versioned<V>> remove(K key) { public CompletableFuture<Versioned<V>> remove(K key) {
checkNotNull(key, ERROR_NULL_KEY); checkNotNull(key, ERROR_NULL_KEY);
checkIfUnmodifiable();
return database.remove(name, keyCache.getUnchecked(key)) return database.remove(name, keyCache.getUnchecked(key))
.thenApply(this::unwrapResult) .thenApply(this::unwrapResult)
.thenApply(v -> v != null .thenApply(v -> v != null
@ -125,6 +130,7 @@ public class DefaultAsyncConsistentMap<K, V> implements AsyncConsistentMap<K, V>
@Override @Override
public CompletableFuture<Void> clear() { public CompletableFuture<Void> clear() {
checkIfUnmodifiable();
return database.clear(name).thenApply(this::unwrapResult); 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) { public CompletableFuture<Versioned<V>> putIfAbsent(K key, V value) {
checkNotNull(key, ERROR_NULL_KEY); checkNotNull(key, ERROR_NULL_KEY);
checkNotNull(value, ERROR_NULL_VALUE); checkNotNull(value, ERROR_NULL_VALUE);
checkIfUnmodifiable();
return database.putIfAbsent(name, return database.putIfAbsent(name,
keyCache.getUnchecked(key), keyCache.getUnchecked(key),
serializer.encode(value)) serializer.encode(value))
@ -169,6 +176,7 @@ public class DefaultAsyncConsistentMap<K, V> implements AsyncConsistentMap<K, V>
public CompletableFuture<Boolean> remove(K key, V value) { public CompletableFuture<Boolean> remove(K key, V value) {
checkNotNull(key, ERROR_NULL_KEY); checkNotNull(key, ERROR_NULL_KEY);
checkNotNull(value, ERROR_NULL_VALUE); checkNotNull(value, ERROR_NULL_VALUE);
checkIfUnmodifiable();
return database.remove(name, keyCache.getUnchecked(key), serializer.encode(value)) return database.remove(name, keyCache.getUnchecked(key), serializer.encode(value))
.thenApply(this::unwrapResult); .thenApply(this::unwrapResult);
} }
@ -176,6 +184,7 @@ public class DefaultAsyncConsistentMap<K, V> implements AsyncConsistentMap<K, V>
@Override @Override
public CompletableFuture<Boolean> remove(K key, long version) { public CompletableFuture<Boolean> remove(K key, long version) {
checkNotNull(key, ERROR_NULL_KEY); checkNotNull(key, ERROR_NULL_KEY);
checkIfUnmodifiable();
return database.remove(name, keyCache.getUnchecked(key), version) return database.remove(name, keyCache.getUnchecked(key), version)
.thenApply(this::unwrapResult); .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) { public CompletableFuture<Boolean> replace(K key, V oldValue, V newValue) {
checkNotNull(key, ERROR_NULL_KEY); checkNotNull(key, ERROR_NULL_KEY);
checkNotNull(newValue, ERROR_NULL_VALUE); checkNotNull(newValue, ERROR_NULL_VALUE);
checkIfUnmodifiable();
byte[] existing = oldValue != null ? serializer.encode(oldValue) : null; byte[] existing = oldValue != null ? serializer.encode(oldValue) : null;
return database.replace(name, keyCache.getUnchecked(key), existing, serializer.encode(newValue)) return database.replace(name, keyCache.getUnchecked(key), existing, serializer.encode(newValue))
.thenApply(this::unwrapResult); .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) { public CompletableFuture<Boolean> replace(K key, long oldVersion, V newValue) {
checkNotNull(key, ERROR_NULL_KEY); checkNotNull(key, ERROR_NULL_KEY);
checkNotNull(newValue, ERROR_NULL_VALUE); checkNotNull(newValue, ERROR_NULL_VALUE);
checkIfUnmodifiable();
return database.replace(name, keyCache.getUnchecked(key), oldVersion, serializer.encode(newValue)) return database.replace(name, keyCache.getUnchecked(key), oldVersion, serializer.encode(newValue))
.thenApply(this::unwrapResult); .thenApply(this::unwrapResult);
} }
@ -216,4 +227,10 @@ public class DefaultAsyncConsistentMap<K, V> implements AsyncConsistentMap<K, V>
throw new IllegalStateException("Must not be here"); throw new IllegalStateException("Must not be here");
} }
} }
private void checkIfUnmodifiable() {
if (readOnly) {
throw new UnsupportedOperationException();
}
}
} }

View File

@ -45,8 +45,9 @@ public class DefaultConsistentMap<K, V> implements ConsistentMap<K, V> {
public DefaultConsistentMap(String name, public DefaultConsistentMap(String name,
Database database, Database database,
Serializer serializer) { Serializer serializer,
asyncMap = new DefaultAsyncConsistentMap<>(name, database, serializer); boolean readOnly) {
asyncMap = new DefaultAsyncConsistentMap<>(name, database, serializer, readOnly);
} }
@Override @Override

View File

@ -19,6 +19,7 @@ public class DefaultConsistentMapBuilder<K, V> implements ConsistentMapBuilder<K
private Serializer serializer; private Serializer serializer;
private String name; private String name;
private boolean partitionsEnabled = true; private boolean partitionsEnabled = true;
private boolean readOnly = false;
private final Database partitionedDatabase; private final Database partitionedDatabase;
private final Database inMemoryDatabase; private final Database inMemoryDatabase;
@ -47,6 +48,12 @@ public class DefaultConsistentMapBuilder<K, V> implements ConsistentMapBuilder<K
return this; return this;
} }
@Override
public ConsistentMapBuilder<K, V> withUpdatesDisabled() {
readOnly = true;
return this;
}
private boolean validInputs() { private boolean validInputs() {
return name != null && serializer != null; return name != null && serializer != null;
} }
@ -57,7 +64,8 @@ public class DefaultConsistentMapBuilder<K, V> implements ConsistentMapBuilder<K
return new DefaultConsistentMap<>( return new DefaultConsistentMap<>(
name, name,
partitionsEnabled ? partitionedDatabase : inMemoryDatabase, partitionsEnabled ? partitionedDatabase : inMemoryDatabase,
serializer); serializer,
readOnly);
} }
@Override @Override
@ -66,6 +74,7 @@ public class DefaultConsistentMapBuilder<K, V> implements ConsistentMapBuilder<K
return new DefaultAsyncConsistentMap<>( return new DefaultAsyncConsistentMap<>(
name, name,
partitionsEnabled ? partitionedDatabase : inMemoryDatabase, partitionsEnabled ? partitionedDatabase : inMemoryDatabase,
serializer); serializer,
readOnly);
} }
} }

View File

@ -33,8 +33,8 @@ public class DefaultDistributedSet<E> implements Set<E> {
private final ConsistentMap<E, Boolean> backingMap; private final ConsistentMap<E, Boolean> backingMap;
public DefaultDistributedSet(String name, Database database, Serializer serializer) { public DefaultDistributedSet(String name, Database database, Serializer serializer, boolean readOnly) {
backingMap = new DefaultConsistentMap<>(name, database, serializer); backingMap = new DefaultConsistentMap<>(name, database, serializer, readOnly);
} }
@Override @Override

View File

@ -34,6 +34,7 @@ public class DefaultSetBuilder<E> implements SetBuilder<E> {
private Serializer serializer; private Serializer serializer;
private String name; private String name;
private final Database database; private final Database database;
private boolean readOnly;
public DefaultSetBuilder(Database database) { public DefaultSetBuilder(Database database) {
this.database = checkNotNull(database); this.database = checkNotNull(database);
@ -53,6 +54,12 @@ public class DefaultSetBuilder<E> implements SetBuilder<E> {
return this; return this;
} }
@Override
public SetBuilder<E> withUpdatesDisabled() {
readOnly = true;
return this;
}
private boolean validInputs() { private boolean validInputs() {
return name != null && serializer != null; return name != null && serializer != null;
} }
@ -60,6 +67,6 @@ public class DefaultSetBuilder<E> implements SetBuilder<E> {
@Override @Override
public Set<E> build() { public Set<E> build() {
checkState(validInputs()); checkState(validInputs());
return new DefaultDistributedSet<>(name, database, serializer); return new DefaultDistributedSet<>(name, database, serializer, readOnly);
} }
} }

View File

@ -72,7 +72,7 @@ public class DefaultTransactionContext implements TransactionContext {
checkNotNull(serializer); checkNotNull(serializer);
return txMaps.computeIfAbsent(mapName, name -> new DefaultTransactionalMap<>( return txMaps.computeIfAbsent(mapName, name -> new DefaultTransactionalMap<>(
name, name,
new DefaultConsistentMap<>(name, database, serializer), new DefaultConsistentMap<>(name, database, serializer, false),
this, this,
serializer)); serializer));
} }

View File

@ -60,7 +60,7 @@ public class TransactionManager {
*/ */
public TransactionManager(Database database) { public TransactionManager(Database database) {
this.database = checkNotNull(database, "database cannot be null"); 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);
} }
/** /**