blob: 4506bbdab9f55f0f6c5193fa7bce70096c182ae1 [file] [log] [blame]
Aaron Kruglikov92511f22015-10-12 14:39:04 -07001/*
2 * Copyright 2015 Open Networking Laboratory
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package org.onosproject.persistence.impl;
18
19import com.google.common.collect.Maps;
20import com.google.common.collect.Sets;
21import org.mapdb.DB;
22import org.mapdb.Hasher;
23import org.onosproject.store.service.Serializer;
24
25import java.util.Collection;
26import java.util.Map;
27import java.util.Set;
28
29import static com.google.common.base.Preconditions.checkNotNull;
30
31
32/**
33 * A map implementation that stores and receives all data from a serialized internal map.
34 */
35public class PersistentMap<K, V> implements Map<K, V> {
36
37 private final Serializer serializer;
38
39 private final org.mapdb.DB database;
40
41 private final Map<byte[], byte[]> items;
42
43 private final String name;
44
45 public PersistentMap(Serializer serializer, DB database, String name) {
46 this.serializer = checkNotNull(serializer);
47 this.database = checkNotNull(database);
48 this.name = checkNotNull(name);
49
50 items = database
51 .createHashMap(name)
52 .keySerializer(org.mapdb.Serializer.BYTE_ARRAY)
53 .valueSerializer(org.mapdb.Serializer.BYTE_ARRAY)
54 .hasher(Hasher.BYTE_ARRAY)
55 .makeOrGet();
56 }
57
58 /**
59 * Reads this set in deserialized form into the provided map.
60 *
61 * @param items the map to be populated
62 */
63 public void readInto(Map<K, V> items) {
64 this.items.forEach((keyBytes, valueBytes) ->
65 items.put(serializer.decode(keyBytes),
66 serializer.decode(valueBytes)));
67 }
68
69 @Override
70 public V remove(Object key) {
71 checkNotNull(key, "Key can not be null.");
72 V removed = get(key);
73 items.remove(serializer.encode(key));
74 return removed;
75 }
76
77 @Override
78 public int size() {
79 return items.size();
80 }
81
82 @Override
83 public boolean isEmpty() {
84 return items.isEmpty();
85 }
86
87 @Override
88 public boolean containsKey(Object key) {
89 checkNotNull(key, "Key cannot be null.");
90 return items.containsKey(serializer.encode(key));
91 }
92
93 @Override
94 public boolean containsValue(Object value) {
95 checkNotNull(value, "Value cannot be null.");
96 byte[] serialized = serializer.encode(value);
97 for (byte[] compareValue : items.values()) {
98 boolean same = true;
99 if (compareValue == null) {
100 same = false;
101 } else if (compareValue.length != serialized.length) {
102 same = false;
103 } else {
104 for (int i = 0; i < serialized.length; i++) {
105 if (serialized[i] != compareValue[i]) {
106 same = false;
107 break;
108 }
109 }
110 }
111 if (same) {
112 return true;
113 }
114 }
115 return false;
116 }
117
118 @Override
119 public V get(Object key) {
120 checkNotNull(key, "Key cannot be null.");
121 return serializer.decode(items.get(serializer.encode(key)));
122 }
123
124 @Override
125 public V put(K key, V value) {
126 checkNotNull(key, "Key cannot be null.");
127 checkNotNull(value, "Value cannot be null.");
128 byte[] prevVal = items.put(serializer.encode(key), serializer.encode(value));
129 if (prevVal == null) {
130 return null;
131 }
132 return serializer.decode(prevVal);
133 }
134
135 @Override
136 public void putAll(Map<? extends K, ? extends V> m) {
137 checkNotNull(m, "The passed in map cannot be null.");
138 m.forEach((k, v) -> items.put(serializer.encode(k), serializer.encode(v)));
139 }
140
141 @Override
142 public void clear() {
143 items.clear();
144 }
145
146 @Override
147 public Set<K> keySet() {
148 Set<K> keys = Sets.newHashSet();
149 items.keySet().forEach(k -> keys.add(serializer.decode(k)));
150 return keys;
151 }
152
153 @Override
154 public Collection<V> values() {
155 Collection<V> values = Sets.newHashSet();
156 items.values().forEach(v -> values.add(serializer.decode(v)));
157 return values;
158 }
159
160 @Override
161 public Set<Entry<K, V>> entrySet() {
162 Set<Entry<K, V>> entries = Sets.newHashSet();
163 items.entrySet().
164 forEach(e -> entries.add(Maps.immutableEntry(serializer.decode(e.getKey()),
165 serializer.decode(e.getValue()))));
166 return entries;
167 }
168
169 @Override
170 public boolean equals(Object map) {
171 //This is not threadsafe and on larger maps incurs a significant processing cost
172 if (!(map instanceof Map)) {
173 return false;
174 }
175 Map asMap = (Map) map;
176 if (this.size() != asMap.size()) {
177 return false;
178 }
179 for (Entry entry : this.entrySet()) {
180 Object key = entry.getKey();
181 if (!asMap.containsKey(key) || !asMap.get(key).equals(entry.getValue())) {
182 return false;
183 }
184 }
185 return true;
186 }
187
188 @Override
189 public int hashCode() {
190 return super.hashCode();
191 }
192}