| /* |
| * Copyright 2015-present 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.Iterators; |
| import org.mapdb.DB; |
| import org.mapdb.Hasher; |
| import org.mapdb.Serializer; |
| |
| import java.util.Collection; |
| import java.util.Iterator; |
| import java.util.Set; |
| |
| import static com.google.common.base.Preconditions.checkNotNull; |
| |
| /** |
| * A set implementation that gets and receives all data from a serialized internal set. |
| */ |
| //TODO add locking for reads and writes |
| public class PersistentSet<E> implements Set<E> { |
| |
| private final org.onosproject.store.service.Serializer serializer; |
| |
| private final org.mapdb.DB database; |
| |
| private final Set<byte[]> items; |
| |
| private final String name; |
| |
| public PersistentSet(org.onosproject.store.service.Serializer serializer, DB database, String name) { |
| this.serializer = checkNotNull(serializer); |
| this.database = checkNotNull(database); |
| this.name = checkNotNull(name); |
| |
| items = database |
| .createHashSet(name) |
| .serializer(Serializer.BYTE_ARRAY) |
| .hasher(Hasher.BYTE_ARRAY) |
| .makeOrGet(); |
| } |
| |
| public void readInto(Set<E> items) { |
| this.items.forEach(item -> items.add(serializer.decode(item))); |
| } |
| |
| @Override |
| public int size() { |
| return items.size(); |
| } |
| |
| @Override |
| public boolean isEmpty() { |
| return items.isEmpty(); |
| } |
| |
| @Override |
| public boolean contains(Object o) { |
| checkNotNull(o, "The argument cannot be null"); |
| return items.contains(serializer.encode(o)); |
| } |
| |
| @Override |
| public Iterator<E> iterator() { |
| return Iterators.transform(items.iterator(), serializer::decode); |
| } |
| |
| @Override |
| public Object[] toArray() { |
| Object[] retArray = new Object[items.size()]; |
| int index = 0; |
| Iterator<byte[]> iterator = items.iterator(); |
| while (iterator.hasNext()) { |
| retArray[index] = serializer.decode(iterator.next()); |
| index++; |
| } |
| return retArray; |
| } |
| |
| @Override |
| public <T> T[] toArray(T[] a) { |
| checkNotNull(a, "The passed in array cannot be null."); |
| int index = 0; |
| Iterator<byte[]> iterator = items.iterator(); |
| T[] retArray; |
| if (a.length >= items.size()) { |
| retArray = a; |
| } else { |
| retArray = (T[]) new Object[items.size()]; |
| } |
| while (iterator.hasNext()) { |
| retArray[index++] = serializer.decode(iterator.next()); |
| } |
| if (retArray.length > items.size()) { |
| retArray[index] = null; |
| } |
| return retArray; |
| } |
| |
| @Override |
| public boolean add(E item) { |
| checkNotNull(item, "Item to be added cannot be null."); |
| return items.add(serializer.encode(item)); |
| } |
| |
| @Override |
| public boolean remove(Object o) { |
| checkNotNull(o, "Item to be removed cannot be null."); |
| return items.remove(serializer.encode(o)); |
| } |
| |
| @Override |
| public boolean containsAll(Collection<?> c) { |
| checkNotNull(c, "Collection cannot be internal."); |
| for (Object item : c) { |
| if (!items.contains(serializer.encode(item))) { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| @Override |
| public boolean addAll(Collection<? extends E> c) { |
| checkNotNull(c, "The collection to be added cannot be null."); |
| boolean changed = false; |
| for (Object item : c) { |
| changed = items.add(serializer.encode(item)) || changed; |
| } |
| return changed; |
| } |
| |
| @Override |
| public boolean retainAll(Collection<?> c) { |
| boolean changed = false; |
| for (byte[] item : items) { |
| E deserialized = serializer.decode(item); |
| if (!c.contains(deserialized)) { |
| changed = items.remove(item) || changed; |
| } |
| } |
| return changed; |
| } |
| |
| @Override |
| public boolean removeAll(Collection<?> c) { |
| boolean changed = false; |
| for (Object item : c) { |
| changed = items.remove(serializer.encode(item)) || changed; |
| } |
| return changed; |
| } |
| |
| @Override |
| public void clear() { |
| items.clear(); |
| } |
| |
| @Override |
| public boolean equals(Object set) { |
| //This is not threadsafe and on larger sets incurs a significant processing cost |
| if (!(set instanceof Set)) { |
| return false; |
| } |
| Set asSet = (Set) set; |
| if (asSet.size() != this.size()) { |
| return false; |
| } |
| for (Object item : this) { |
| if (!asSet.contains(item)) { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| @Override |
| public int hashCode() { |
| return super.hashCode(); |
| } |
| } |