diff options
Diffstat (limited to 'framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/PersistentMap.java')
-rw-r--r-- | framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/PersistentMap.java | 192 |
1 files changed, 192 insertions, 0 deletions
diff --git a/framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/PersistentMap.java b/framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/PersistentMap.java new file mode 100644 index 00000000..4506bbda --- /dev/null +++ b/framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/PersistentMap.java @@ -0,0 +1,192 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onosproject.persistence.impl; + +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; +import org.mapdb.DB; +import org.mapdb.Hasher; +import org.onosproject.store.service.Serializer; + +import java.util.Collection; +import java.util.Map; +import java.util.Set; + +import static com.google.common.base.Preconditions.checkNotNull; + + +/** + * A map implementation that stores and receives all data from a serialized internal map. + */ +public class PersistentMap<K, V> implements Map<K, V> { + + private final Serializer serializer; + + private final org.mapdb.DB database; + + private final Map<byte[], byte[]> items; + + private final String name; + + public PersistentMap(Serializer serializer, DB database, String name) { + this.serializer = checkNotNull(serializer); + this.database = checkNotNull(database); + this.name = checkNotNull(name); + + items = database + .createHashMap(name) + .keySerializer(org.mapdb.Serializer.BYTE_ARRAY) + .valueSerializer(org.mapdb.Serializer.BYTE_ARRAY) + .hasher(Hasher.BYTE_ARRAY) + .makeOrGet(); + } + + /** + * Reads this set in deserialized form into the provided map. + * + * @param items the map to be populated + */ + public void readInto(Map<K, V> items) { + this.items.forEach((keyBytes, valueBytes) -> + items.put(serializer.decode(keyBytes), + serializer.decode(valueBytes))); + } + + @Override + public V remove(Object key) { + checkNotNull(key, "Key can not be null."); + V removed = get(key); + items.remove(serializer.encode(key)); + return removed; + } + + @Override + public int size() { + return items.size(); + } + + @Override + public boolean isEmpty() { + return items.isEmpty(); + } + + @Override + public boolean containsKey(Object key) { + checkNotNull(key, "Key cannot be null."); + return items.containsKey(serializer.encode(key)); + } + + @Override + public boolean containsValue(Object value) { + checkNotNull(value, "Value cannot be null."); + byte[] serialized = serializer.encode(value); + for (byte[] compareValue : items.values()) { + boolean same = true; + if (compareValue == null) { + same = false; + } else if (compareValue.length != serialized.length) { + same = false; + } else { + for (int i = 0; i < serialized.length; i++) { + if (serialized[i] != compareValue[i]) { + same = false; + break; + } + } + } + if (same) { + return true; + } + } + return false; + } + + @Override + public V get(Object key) { + checkNotNull(key, "Key cannot be null."); + return serializer.decode(items.get(serializer.encode(key))); + } + + @Override + public V put(K key, V value) { + checkNotNull(key, "Key cannot be null."); + checkNotNull(value, "Value cannot be null."); + byte[] prevVal = items.put(serializer.encode(key), serializer.encode(value)); + if (prevVal == null) { + return null; + } + return serializer.decode(prevVal); + } + + @Override + public void putAll(Map<? extends K, ? extends V> m) { + checkNotNull(m, "The passed in map cannot be null."); + m.forEach((k, v) -> items.put(serializer.encode(k), serializer.encode(v))); + } + + @Override + public void clear() { + items.clear(); + } + + @Override + public Set<K> keySet() { + Set<K> keys = Sets.newHashSet(); + items.keySet().forEach(k -> keys.add(serializer.decode(k))); + return keys; + } + + @Override + public Collection<V> values() { + Collection<V> values = Sets.newHashSet(); + items.values().forEach(v -> values.add(serializer.decode(v))); + return values; + } + + @Override + public Set<Entry<K, V>> entrySet() { + Set<Entry<K, V>> entries = Sets.newHashSet(); + items.entrySet(). + forEach(e -> entries.add(Maps.immutableEntry(serializer.decode(e.getKey()), + serializer.decode(e.getValue())))); + return entries; + } + + @Override + public boolean equals(Object map) { + //This is not threadsafe and on larger maps incurs a significant processing cost + if (!(map instanceof Map)) { + return false; + } + Map asMap = (Map) map; + if (this.size() != asMap.size()) { + return false; + } + for (Entry entry : this.entrySet()) { + Object key = entry.getKey(); + if (!asMap.containsKey(key) || !asMap.get(key).equals(entry.getValue())) { + return false; + } + } + return true; + } + + @Override + public int hashCode() { + return super.hashCode(); + } +}
\ No newline at end of file |