All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sleepycat.collections.StoredMap Maven / Gradle / Ivy

Go to download

Berkeley DB Java Edition is a open source, transactional storage solution for Java applications. The Direct Persistence Layer (DPL) API is faster and easier to develop, deploy, and manage than serialized object files or ORM-based Java persistence solutions. The Collections API enhances the standard java.util.collections classes allowing them to be persisted to a local file system and accessed concurrently while protected by ACID transactions. Data is stored by serializing objects and managing class and instance data separately so as not to waste space. Berkeley DB Java Edition is the reliable drop-in solution for complex, fast, and scalable storage. Source for this release is in 'je-4.0.92-sources.jar', the Javadoc is located at 'http://download.oracle.com/berkeley-db/docs/je/4.0.92/'.

There is a newer version: 5.0.73
Show newest version
/*-
 * Copyright (C) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
 *
 * This file was distributed by Oracle as part of a version of Oracle Berkeley
 * DB Java Edition made available at:
 *
 * http://www.oracle.com/technetwork/database/database-technologies/berkeleydb/downloads/index.html
 *
 * Please see the LICENSE file included in the top-level directory of the
 * appropriate version of Oracle Berkeley DB Java Edition for a copy of the
 * license and additional information.
 */

package com.sleepycat.collections;

import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentMap;

import com.sleepycat.bind.EntityBinding;
import com.sleepycat.bind.EntryBinding;
import com.sleepycat.je.Database;
/*  */
import com.sleepycat.je.EnvironmentFailureException; // for javadoc
import com.sleepycat.je.OperationFailureException; // for javadoc
/*  */
import com.sleepycat.je.OperationStatus;
import com.sleepycat.util.RuntimeExceptionWrapper;
import com.sleepycat.util.keyrange.KeyRangeException;

/**
 * A Map view of a {@link Database}.
 *
 * 

In addition to the standard Map methods, this class provides the * following methods for stored maps only. Note that the use of these methods * is not compatible with the standard Java collections interface.

*
    *
  • {@link #duplicates}
  • *
  • {@link #duplicatesMap}
  • *
  • {@link #append}
  • *
* * @author Mark Hayes */ public class StoredMap extends StoredContainer implements ConcurrentMap { private StoredKeySet keySet; private StoredEntrySet entrySet; private StoredValueSet valueSet; /** * Creates a map view of a {@link Database}. * * @param database is the Database underlying the new collection. * * @param keyBinding is the binding used to translate between key buffers * and key objects. * * @param valueBinding is the binding used to translate between value * buffers and value objects. * * @param writeAllowed is true to create a read-write collection or false * to create a read-only collection. * * @throws IllegalArgumentException if formats are not consistently * defined or a parameter is invalid. * * @throws RuntimeExceptionWrapper if a checked exception is thrown, * including a {@code DatabaseException} on BDB (C edition). */ public StoredMap(Database database, EntryBinding keyBinding, EntryBinding valueBinding, boolean writeAllowed) { super(new DataView(database, keyBinding, valueBinding, null, writeAllowed, null)); initView(); } /** * Creates a map view of a {@link Database} with a {@link * PrimaryKeyAssigner}. Writing is allowed for the created map. * * @param database is the Database underlying the new collection. * * @param keyBinding is the binding used to translate between key buffers * and key objects. * * @param valueBinding is the binding used to translate between value * buffers and value objects. * * @param keyAssigner is used by the {@link #append} method to assign * primary keys. * * @throws IllegalArgumentException if formats are not consistently * defined or a parameter is invalid. * * @throws RuntimeExceptionWrapper if a checked exception is thrown, * including a {@code DatabaseException} on BDB (C edition). */ public StoredMap(Database database, EntryBinding keyBinding, EntryBinding valueBinding, PrimaryKeyAssigner keyAssigner) { super(new DataView(database, keyBinding, valueBinding, null, true, keyAssigner)); initView(); } /** * Creates a map entity view of a {@link Database}. * * @param database is the Database underlying the new collection. * * @param keyBinding is the binding used to translate between key buffers * and key objects. * * @param valueEntityBinding is the binding used to translate between * key/value buffers and entity value objects. * * @param writeAllowed is true to create a read-write collection or false * to create a read-only collection. * * @throws IllegalArgumentException if formats are not consistently * defined or a parameter is invalid. * * @throws RuntimeExceptionWrapper if a checked exception is thrown, * including a {@code DatabaseException} on BDB (C edition). */ public StoredMap(Database database, EntryBinding keyBinding, EntityBinding valueEntityBinding, boolean writeAllowed) { super(new DataView(database, keyBinding, null, valueEntityBinding, writeAllowed, null)); initView(); } /** * Creates a map entity view of a {@link Database} with a {@link * PrimaryKeyAssigner}. Writing is allowed for the created map. * * @param database is the Database underlying the new collection. * * @param keyBinding is the binding used to translate between key buffers * and key objects. * * @param valueEntityBinding is the binding used to translate between * key/value buffers and entity value objects. * * @param keyAssigner is used by the {@link #append} method to assign * primary keys. * * @throws IllegalArgumentException if formats are not consistently * defined or a parameter is invalid. * * @throws RuntimeExceptionWrapper if a checked exception is thrown, * including a {@code DatabaseException} on BDB (C edition). */ public StoredMap(Database database, EntryBinding keyBinding, EntityBinding valueEntityBinding, PrimaryKeyAssigner keyAssigner) { super(new DataView(database, keyBinding, null, valueEntityBinding, true, keyAssigner)); initView(); } StoredMap(DataView view) { super(view); initView(); } /** * Override this method to initialize view-dependent fields. */ void initAfterClone() { initView(); } /** * The keySet, entrySet and valueSet are created during Map construction * rather than lazily when requested (as done with the java.util.Map * implementations). This is done to avoid synchronization every time they * are requested. Since they are requested often but a StoredMap is * created infrequently, this gives the best performance. The additional * views are small objects and are cheap to construct. */ private void initView() { /* entrySet */ if (areKeyRangesAllowed()) { entrySet = new StoredSortedEntrySet(view); } else { entrySet = new StoredEntrySet(view); } /* keySet */ DataView newView = view.keySetView(); if (areKeyRangesAllowed()) { keySet = new StoredSortedKeySet(newView); } else { keySet = new StoredKeySet(newView); } /* valueSet */ newView = view.valueSetView(); if (areKeyRangesAllowed() && newView.canDeriveKeyFromValue()) { valueSet = new StoredSortedValueSet(newView); } else { valueSet = new StoredValueSet(newView); } } /** * Returns the value to which this map maps the specified key. If * duplicates are allowed, this method returns the first duplicate, in the * order in which duplicates are configured, that maps to the specified * key. * * This method conforms to the {@link Map#get} interface. * * * @throws OperationFailureException if one of the Read Operation * Failures occurs. * * @throws EnvironmentFailureException if an unexpected, internal or * environment-wide failure occurs. * * * @throws RuntimeExceptionWrapper if a checked exception is thrown, * including a {@code DatabaseException} on BDB (C edition). */ public V get(Object key) { return (V) getValue(key); } /** * Associates the specified value with the specified key in this map * (optional operation). If duplicates are allowed and the specified key * is already mapped to a value, this method appends the new duplicate * after the existing duplicates. This method conforms to the {@link * Map#put} interface. * *

The key parameter may be null if an entity binding is used and the * key will be derived from the value (entity) parameter. If an entity * binding is used and the key parameter is non-null, then the key * parameter must be equal to the key derived from the value parameter.

* * @return the previous value associated with specified key, or null if * there was no mapping for the key or if duplicates are allowed. * * * @throws OperationFailureException if one of the Write * Operation Failures occurs. * * @throws EnvironmentFailureException if an unexpected, internal or * environment-wide failure occurs. * * * @throws UnsupportedOperationException if the collection is indexed, or * if the collection is read-only. * * @throws IllegalArgumentException if an entity value binding is used and * the primary key of the value given is different than the existing stored * primary key. * * @throws RuntimeExceptionWrapper if a checked exception is thrown, * including a {@code DatabaseException} on BDB (C edition). */ public V put(K key, V value) { return (V) putKeyValue(key, value); } /** * Appends a given value returning the newly assigned key. If a {@link * PrimaryKeyAssigner} is associated with Store for this map, it will be * used to assigned the returned key. Otherwise the Store must be a QUEUE * or RECNO database and the next available record number is assigned as * the key. This method does not exist in the standard {@link Map} * interface. * *

Note that for the JE product, QUEUE and RECNO databases are not * supported, and therefore a PrimaryKeyAssigner must be associated with * the map in order to call this method.

* * @param value the value to be appended. * * @return the assigned key. * * * @throws OperationFailureException if one of the Write * Operation Failures occurs. * * @throws EnvironmentFailureException if an unexpected, internal or * environment-wide failure occurs. * * * @throws UnsupportedOperationException if the collection is indexed, or * if the collection is read-only, or if the Store has no {@link * PrimaryKeyAssigner} and is not a QUEUE or RECNO database. * * @throws RuntimeExceptionWrapper if a checked exception is thrown, * including a {@code DatabaseException} on BDB (C edition). */ public K append(V value) { boolean doAutoCommit = beginAutoCommit(); try { Object[] key = new Object[1]; view.append(value, key, null); commitAutoCommit(doAutoCommit); return (K) key[0]; } catch (Exception e) { throw handleException(e, doAutoCommit); } } /** * Removes the mapping for this key from this map if present (optional * operation). If duplicates are allowed, this method removes all * duplicates for the given key. This method conforms to the {@link * Map#remove} interface. * * * @throws OperationFailureException if one of the Write * Operation Failures occurs. * * @throws EnvironmentFailureException if an unexpected, internal or * environment-wide failure occurs. * * * @throws UnsupportedOperationException if the collection is read-only. * * @throws RuntimeExceptionWrapper if a checked exception is thrown, * including a {@code DatabaseException} on BDB (C edition). */ public V remove(Object key) { Object[] oldVal = new Object[1]; removeKey(key, oldVal); return (V) oldVal[0]; } /** * If the specified key is not already associated with a value, associate * it with the given value. This method conforms to the {@link * ConcurrentMap#putIfAbsent} interface. * * * @throws OperationFailureException if one of the Write * Operation Failures occurs. * * @throws EnvironmentFailureException if an unexpected, internal or * environment-wide failure occurs. * * * @throws RuntimeExceptionWrapper if a checked exception is thrown, * including a {@code DatabaseException} on BDB (C edition). */ public V putIfAbsent(K key, V value) { DataCursor cursor = null; boolean doAutoCommit = beginAutoCommit(); try { cursor = new DataCursor(view, true); V oldValue; while (true) { OperationStatus status = cursor.putNoOverwrite(key, value, false /*useCurrentKey*/); if (status == OperationStatus.SUCCESS) { /* We inserted the key. Return null. */ oldValue = null; break; } else { status = cursor.getSearchKey(key, null /*value*/, false /*lockForWrite*/); if (status == OperationStatus.SUCCESS) { /* The key is present. Return the current value. */ oldValue = (V) cursor.getCurrentValue(); break; } else { /* * If Serializable isolation is not configured, another * thread can delete the record after our attempt to * insert it failed above. Loop back and try again. */ continue; } } } closeCursor(cursor); commitAutoCommit(doAutoCommit); return oldValue; } catch (Exception e) { closeCursor(cursor); throw handleException(e, doAutoCommit); } } /** * Remove entry for key only if currently mapped to given value. This * method conforms to the {@link ConcurrentMap#remove(Object,Object)} * interface. * * * @throws OperationFailureException if one of the Write * Operation Failures occurs. * * @throws EnvironmentFailureException if an unexpected, internal or * environment-wide failure occurs. * * * @throws RuntimeExceptionWrapper if a checked exception is thrown, * including a {@code DatabaseException} on BDB (C edition). */ public boolean remove(Object key, Object value) { DataCursor cursor = null; boolean doAutoCommit = beginAutoCommit(); try { cursor = new DataCursor(view, true, key); OperationStatus status = cursor.getFirst(true /*lockForWrite*/); boolean removed; if (status == OperationStatus.SUCCESS && cursor.getCurrentValue().equals(value)) { cursor.delete(); removed = true; } else { removed = false; } closeCursor(cursor); commitAutoCommit(doAutoCommit); return removed; } catch (Exception e) { closeCursor(cursor); throw handleException(e, doAutoCommit); } } /** * Replace entry for key only if currently mapped to some value. This * method conforms to the {@link ConcurrentMap#replace(Object,Object)} * interface. * * * @throws OperationFailureException if one of the Write * Operation Failures occurs. * * @throws EnvironmentFailureException if an unexpected, internal or * environment-wide failure occurs. * * * @throws RuntimeExceptionWrapper if a checked exception is thrown, * including a {@code DatabaseException} on BDB (C edition). */ public V replace(K key, V value) { DataCursor cursor = null; boolean doAutoCommit = beginAutoCommit(); try { cursor = new DataCursor(view, true, key); OperationStatus status = cursor.getFirst(true /*lockForWrite*/); V oldValue; if (status == OperationStatus.SUCCESS) { oldValue = (V) cursor.getCurrentValue(); cursor.putCurrent(value); } else { oldValue = null; } closeCursor(cursor); commitAutoCommit(doAutoCommit); return oldValue; } catch (Exception e) { closeCursor(cursor); throw handleException(e, doAutoCommit); } } /** * Replace entry for key only if currently mapped to given value. This * method conforms to the {@link * ConcurrentMap#replace(Object,Object,Object)} interface. * * * @throws OperationFailureException if one of the Write * Operation Failures occurs. * * @throws EnvironmentFailureException if an unexpected, internal or * environment-wide failure occurs. * * * @throws RuntimeExceptionWrapper if a checked exception is thrown, * including a {@code DatabaseException} on BDB (C edition). */ public boolean replace(K key, V oldValue, V newValue) { DataCursor cursor = null; boolean doAutoCommit = beginAutoCommit(); try { cursor = new DataCursor(view, true, key); OperationStatus status = cursor.getFirst(true /*lockForWrite*/); boolean replaced; if (status == OperationStatus.SUCCESS && cursor.getCurrentValue().equals(oldValue)) { cursor.putCurrent(newValue); replaced = true; } else { replaced = false; } closeCursor(cursor); commitAutoCommit(doAutoCommit); return replaced; } catch (Exception e) { closeCursor(cursor); throw handleException(e, doAutoCommit); } } /** * Returns true if this map contains the specified key. This method * conforms to the {@link Map#containsKey} interface. * * * @throws OperationFailureException if one of the Read Operation * Failures occurs. * * @throws EnvironmentFailureException if an unexpected, internal or * environment-wide failure occurs. * * * @throws RuntimeExceptionWrapper if a checked exception is thrown, * including a {@code DatabaseException} on BDB (C edition). */ public boolean containsKey(Object key) { return super.containsKey(key); } /** * Returns true if this map contains the specified value. When an entity * binding is used, this method returns whether the map contains the * primary key and value mapping of the entity. This method conforms to * the {@link Map#containsValue} interface. * * * @throws OperationFailureException if one of the Read Operation * Failures occurs. * * @throws EnvironmentFailureException if an unexpected, internal or * environment-wide failure occurs. * * * @throws RuntimeExceptionWrapper if a checked exception is thrown, * including a {@code DatabaseException} on BDB (C edition). */ public boolean containsValue(Object value) { return super.containsValue(value); } /** * Copies all of the mappings from the specified map to this map (optional * operation). When duplicates are allowed, the mappings in the specified * map are effectively appended to the existing mappings in this map, that * is no previously existing mappings in this map are replaced. This * method conforms to the {@link Map#putAll} interface. * * * @throws OperationFailureException if one of the Write * Operation Failures occurs. * * @throws EnvironmentFailureException if an unexpected, internal or * environment-wide failure occurs. * * * @throws UnsupportedOperationException if the collection is read-only, or * if the collection is indexed. * * @throws RuntimeExceptionWrapper if a checked exception is thrown, * including a {@code DatabaseException} on BDB (C edition). */ public void putAll(Map map) { boolean doAutoCommit = beginAutoCommit(); Iterator i = null; try { Collection coll = map.entrySet(); i = storedOrExternalIterator(coll); while (i.hasNext()) { Map.Entry entry = (Map.Entry) i.next(); putKeyValue(entry.getKey(), entry.getValue()); } StoredIterator.close(i); commitAutoCommit(doAutoCommit); } catch (Exception e) { StoredIterator.close(i); throw handleException(e, doAutoCommit); } } /** * Returns a set view of the keys contained in this map. A {@link * java.util.SortedSet} is returned if the map supports key ranges. The * returned collection will be read-only if the map is read-only. This * method conforms to the {@link Map#keySet()} interface. * *

Note that the return value is a StoredCollection and must be treated * as such; for example, its iterators must be explicitly closed.

* * @return a {@link StoredKeySet} or a {@link StoredSortedKeySet} for this * map. * * @throws RuntimeExceptionWrapper if a checked exception is thrown, * including a {@code DatabaseException} on BDB (C edition). * * @see #areKeyRangesAllowed * @see #isWriteAllowed */ public Set keySet() { return keySet; } /** * Returns a set view of the mappings contained in this map. A {@link * java.util.SortedSet} is returned if the map supports key ranges. The * returned collection will be read-only if the map is read-only. This * method conforms to the {@link Map#entrySet()} interface. * *

Note that the return value is a StoredCollection and must be treated * as such; for example, its iterators must be explicitly closed.

* * @return a {@link StoredEntrySet} or a {@link StoredSortedEntrySet} for * this map. * * @throws RuntimeExceptionWrapper if a checked exception is thrown, * including a {@code DatabaseException} on BDB (C edition). * * @see #areKeyRangesAllowed * @see #isWriteAllowed */ public Set> entrySet() { return entrySet; } /** * Returns a collection view of the values contained in this map. A {@link * java.util.SortedSet} is returned if the map supports key ranges and the * value/entity binding can be used to derive the map's key from its * value/entity object. The returned collection will be read-only if the * map is read-only. This method conforms to the {@link Map#values()} * interface. * *

Note that the return value is a StoredCollection and must be treated * as such; for example, its iterators must be explicitly closed.

* * @return a {@link StoredValueSet} or a {@link StoredSortedValueSet} for * this map. * * @throws RuntimeExceptionWrapper if a checked exception is thrown, * including a {@code DatabaseException} on BDB (C edition). * * @see #areKeyRangesAllowed * @see #isWriteAllowed */ public Collection values() { return valueSet; } /** * Returns a new collection containing the values mapped to the given key * in this map. This collection's iterator() method is particularly useful * for iterating over the duplicates for a given key, since this is not * supported by the standard Map interface. This method does not exist in * the standard {@link Map} interface. * *

If no mapping for the given key is present, an empty collection is * returned. If duplicates are not allowed, at most a single value will be * in the collection returned. If duplicates are allowed, the returned * collection's add() method may be used to add values for the given * key.

* * @param key is the key for which values are to be returned. * * @return the new collection. * * @throws RuntimeExceptionWrapper if a checked exception is thrown, * including a {@code DatabaseException} on BDB (C edition). */ public Collection duplicates(K key) { try { DataView newView = view.valueSetView(key); return new StoredValueSet(newView); } catch (KeyRangeException e) { return Collections.EMPTY_SET; } catch (Exception e) { throw StoredContainer.convertException(e); } } /** * Returns a new map from primary key to value for the subset of records * having a given secondary key (duplicates). This method does not exist * in the standard {@link Map} interface. * *

If no mapping for the given key is present, an empty collection is * returned. If duplicates are not allowed, at most a single value will be * in the collection returned. If duplicates are allowed, the returned * collection's add() method may be used to add values for the given * key.

* * @param secondaryKey is the secondary key for which duplicates values * will be represented by the returned map. * * @param primaryKeyBinding is the binding used for keys in the returned * map. * * @param the primary key class. * * @return the new map. * * @throws RuntimeExceptionWrapper if a checked exception is thrown, * including a {@code DatabaseException} on BDB (C edition). */ public Map duplicatesMap(K secondaryKey, EntryBinding primaryKeyBinding) { try { DataView newView = view.duplicatesView(secondaryKey, primaryKeyBinding); if (isOrdered()) { return new StoredSortedMap(newView); } else { return new StoredMap(newView); } } catch (Exception e) { throw StoredContainer.convertException(e); } } /** * Compares the specified object with this map for equality. A value * comparison is performed by this method and the stored values are * compared rather than calling the equals() method of each element. This * method conforms to the {@link Map#equals} interface. * * * @throws OperationFailureException if one of the Read Operation * Failures occurs. * * @throws EnvironmentFailureException if an unexpected, internal or * environment-wide failure occurs. * * * @throws RuntimeExceptionWrapper if a checked exception is thrown, * including a {@code DatabaseException} on BDB (C edition). */ public boolean equals(Object other) { if (other instanceof Map) { return entrySet().equals(((Map) other).entrySet()); } else { return false; } } /* * Add this in to keep FindBugs from whining at us about implementing * equals(), but not hashCode(). */ public int hashCode() { return super.hashCode(); } // Inherit javadoc public int size() { return values().size(); } /** * Converts the map to a string representation for debugging. WARNING: All * mappings will be converted to strings and returned and therefore the * returned string may be very large. * * @return the string representation. * * @throws RuntimeExceptionWrapper if a checked exception is thrown, * including a {@code DatabaseException} on BDB (C edition). */ public String toString() { return entrySet().toString(); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy