create MapClosable which replaces the default isClosed() method that was removed from chronicle closable

This commit is contained in:
Rob Austin
2020-05-29 16:40:58 +01:00
parent 1a2468b6d4
commit f042add96b
6 changed files with 57 additions and 80 deletions
@@ -17,8 +17,8 @@
package net.openhft.chronicle.hash;
import net.openhft.chronicle.bytes.BytesStore;
import net.openhft.chronicle.core.io.Closeable;
import net.openhft.chronicle.map.ChronicleMap;
import net.openhft.chronicle.map.MapClosable;
import net.openhft.chronicle.map.MapMethods;
import net.openhft.chronicle.map.MapQueryContext;
import net.openhft.chronicle.set.ChronicleSet;
@@ -35,43 +35,37 @@ import java.util.function.Predicate;
* Common base interface for {@link ChronicleMap} and {@link ChronicleSet}.
*/
public interface ChronicleHash<K, E extends HashEntry<K>, SC extends HashSegmentContext<K, ?>,
EQC extends ExternalHashQueryContext<K>> extends Closeable {
EQC extends ExternalHashQueryContext<K>> extends MapClosable {
/**
* Returns the file this hash container mapped to, i. e. when it is created by
* {@link ChronicleHashBuilder#create()} call, or {@code null} if it is purely in-memory,
* i. e. if it is created by {@link ChronicleHashBuilder#create()} call.
* Returns the file this hash container mapped to, i. e. when it is created by {@link ChronicleHashBuilder#create()} call, or {@code null} if it
* is purely in-memory, i. e. if it is created by {@link ChronicleHashBuilder#create()} call.
*
* @return the file this {@link ChronicleMap} or {@link ChronicleSet} is mapped to,
* or {@code null} if it is not mapped to any file
* @return the file this {@link ChronicleMap} or {@link ChronicleSet} is mapped to, or {@code null} if it is not mapped to any file
* @see ChronicleHashBuilder#createPersistedTo(File)
*/
File file();
/**
* Returns the name of this {@code ChronicleHash}, configured by {@link
* ChronicleHashBuilder#name(String)}, or {@code null}, if not configured.
* Returns the name of this {@code ChronicleHash}, configured by {@link ChronicleHashBuilder#name(String)}, or {@code null}, if not configured.
*
* @return the name of this this {@link ChronicleMap} or {@link ChronicleSet}
*/
String name();
/**
* Returns a {@code String}, useful for identifying this {@code ChronicleHash} in debugging,
* logging, and error reporting. {@link #toString()} of concrete {@code ChronicleHash}
* subinterfaces, {@link ChronicleMap} and {@link ChronicleSet}, has to follow {@link
* Map#toString()} and {@link Set#toString()} contracts respectively, making it not always
* useful (or even impossible to use, if this {@code ChronicleHash} contains a lot of entries)
* for the purposes listed above.
* Returns a {@code String}, useful for identifying this {@code ChronicleHash} in debugging, logging, and error reporting. {@link #toString()} of
* concrete {@code ChronicleHash} subinterfaces, {@link ChronicleMap} and {@link ChronicleSet}, has to follow {@link Map#toString()} and {@link
* Set#toString()} contracts respectively, making it not always useful (or even impossible to use, if this {@code ChronicleHash} contains a lot of
* entries) for the purposes listed above.
* <p>
* <p>This method return a string of the form:<br><br>
* [ChronicleMap|ChronicleSet]{name={@link #name()}, file={@link #file()},
* identityHashCode={@link System#identityHashCode System.identityHashCode(thisChronicleHash)}}
* [ChronicleMap|ChronicleSet]{name={@link #name()}, file={@link #file()}, identityHashCode={@link System#identityHashCode
* System.identityHashCode(thisChronicleHash)}}
* <br><br>
* This form could be changed in any subsequent Chronicle Map library release (including patch
* release). The user code shouldn't depend on this form.
* This form could be changed in any subsequent Chronicle Map library release (including patch release). The user code shouldn't depend on this
* form.
*
* @return a {@code String}, useful for identifying this {@code ChronicleHash} in debugging,
* logging, and error reporting
* @return a {@code String}, useful for identifying this {@code ChronicleHash} in debugging, logging, and error reporting
*/
String toIdentityString();
@@ -83,8 +77,8 @@ public interface ChronicleHash<K, E extends HashEntry<K>, SC extends HashSegment
long longSize();
/**
* Returns the amount of off-heap memory (in bytes), allocated by this {@code ChronicleHash} or
* shared with with other ChronicleHashes, persisting to the same {@link #file()}.
* Returns the amount of off-heap memory (in bytes), allocated by this {@code ChronicleHash} or shared with with other ChronicleHashes, persisting
* to the same {@link #file()}.
* <p>
* <p>After {@link #close()} this method returns 0.
*
@@ -110,8 +104,7 @@ public interface ChronicleHash<K, E extends HashEntry<K>, SC extends HashSegment
* }}</pre>
* <p>
* <p>See documentation to {@link HashQueryContext} interface and methods in {@link MapMethods}
* interface for examples of using contexts. Also see <a href="
* https://github.com/OpenHFT/Chronicle-Map#working-with-an-entry-within-a-context-section">
* interface for examples of using contexts. Also see <a href=" https://github.com/OpenHFT/Chronicle-Map#working-with-an-entry-within-a-context-section">
* Working with an entry within a context</a> section in the Chronicle Map tutorial.
*
* @param key the queried key
@@ -125,15 +118,12 @@ public interface ChronicleHash<K, E extends HashEntry<K>, SC extends HashSegment
EQC queryContext(K key);
/**
* Returns a context to perform arbitrary operations with the given key, provided in
* {@link Data} form. Equivalent to {@link #queryContext(Object)}, but accepts {@code Data}
* instead of object key. This method is useful, when you already have {@code Data}, calling
* this method instead of {@link #queryContext(Object)} might help to avoid unnecessary
* deserialization.
* Returns a context to perform arbitrary operations with the given key, provided in {@link Data} form. Equivalent to {@link
* #queryContext(Object)}, but accepts {@code Data} instead of object key. This method is useful, when you already have {@code Data}, calling this
* method instead of {@link #queryContext(Object)} might help to avoid unnecessary deserialization.
* <p>
* <p>See documentation to {@link HashQueryContext} interface and methods in {@link MapMethods}
* interface for examples of using contexts. Also see <a href="
* https://github.com/OpenHFT/Chronicle-Map#working-with-an-entry-within-a-context-section">
* interface for examples of using contexts. Also see <a href=" https://github.com/OpenHFT/Chronicle-Map#working-with-an-entry-within-a-context-section">
* Working with an entry within a context</a> section in the Chronicle Map tutorial.
*
* @param key the queried key as {@code Data}
@@ -143,9 +133,8 @@ public interface ChronicleHash<K, E extends HashEntry<K>, SC extends HashSegment
EQC queryContext(Data<K> key);
/**
* Returns a context to perform arbitrary operations with the given key, provided in the
* serialized form. See {@link #queryContext(Object)} and {@link #queryContext(Data)} for more
* information on contexts semantics and usage patterns.
* Returns a context to perform arbitrary operations with the given key, provided in the serialized form. See {@link #queryContext(Object)} and
* {@link #queryContext(Data)} for more information on contexts semantics and usage patterns.
*
* @param keyBytes the bytes store with the key bytes to query
* @param offset actual offset of the key bytes within the given BytesStore
@@ -156,8 +145,7 @@ public interface ChronicleHash<K, E extends HashEntry<K>, SC extends HashSegment
EQC queryContext(BytesStore keyBytes, long offset, long size);
/**
* Returns a context of the segment with the given index. Segments are indexed from 0 to
* {@link #segments()}{@code - 1}.
* Returns a context of the segment with the given index. Segments are indexed from 0 to {@link #segments()}{@code - 1}.
*
* @see HashSegmentContext
*/
@@ -172,50 +160,43 @@ public interface ChronicleHash<K, E extends HashEntry<K>, SC extends HashSegment
int segments();
/**
* Checks the given predicate on each entry in this {@code ChronicleHash} until all entries
* have been processed or the predicate returns {@code false} for some entry, or throws
* an {@code Exception}. Exceptions thrown by the predicate are relayed to the caller.
* Checks the given predicate on each entry in this {@code ChronicleHash} until all entries have been processed or the predicate returns {@code
* false} for some entry, or throws an {@code Exception}. Exceptions thrown by the predicate are relayed to the caller.
* <p>
* <p>The order in which the entries will be processed is unspecified. It might differ from
* the order of iteration via {@code Iterator} returned by any method of this
* {@code ChronicleHash} or it's collection view.
* the order of iteration via {@code Iterator} returned by any method of this {@code ChronicleHash} or it's collection view.
* <p>
* <p>If the {@code ChronicleHash} is empty, this method returns {@code true} immediately.
*
* @param predicate the predicate to be checked for each entry
* @return {@code true} if the predicate returned {@code true} for all entries of
* the {@code ChronicleHash}, {@code false} if it returned {@code false} for the entry
* @return {@code true} if the predicate returned {@code true} for all entries of the {@code ChronicleHash}, {@code false} if it returned {@code
* false} for the entry
*/
boolean forEachEntryWhile(Predicate<? super E> predicate);
/**
* Performs the given action for each entry in this {@code ChronicleHash} until all entries have
* been processed or the action throws an {@code Exception}. Exceptions thrown by the action are
* relayed to the caller.
* Performs the given action for each entry in this {@code ChronicleHash} until all entries have been processed or the action throws an {@code
* Exception}. Exceptions thrown by the action are relayed to the caller.
* <p>
* <p>The order in which the entries will be processed is unspecified. It might differ from
* the order of iteration via {@code Iterator} returned by any method of this
* {@code ChronicleHash} or it's collection view.
* the order of iteration via {@code Iterator} returned by any method of this {@code ChronicleHash} or it's collection view.
*
* @param action the action to be performed for each entry
*/
void forEachEntry(Consumer<? super E> action);
/**
* Releases the off-heap memory, used by this hash container and resources, used by replication,
* if any. However, if hash container (hence off-heap memory, used by it) is mapped to the file
* and there are other instances mapping the same data on the server across JVMs, the memory
* won't be actually freed on operating system level. I. e. this method call doesn't affect
* other {@link ChronicleMap} or {@link ChronicleSet} instances mapping the same data.
* Releases the off-heap memory, used by this hash container and resources, used by replication, if any. However, if hash container (hence
* off-heap memory, used by it) is mapped to the file and there are other instances mapping the same data on the server across JVMs, the memory
* won't be actually freed on operating system level. I. e. this method call doesn't affect other {@link ChronicleMap} or {@link ChronicleSet}
* instances mapping the same data.
* <p>
* <p>If you won't call this method, memory would be held at least until next garbage
* collection. This could be a problem if, for example, you target rare garbage collections,
* but load and drop {@code ChronicleHash}es regularly.
* collection. This could be a problem if, for example, you target rare garbage collections, but load and drop {@code ChronicleHash}es regularly.
* <p>
* <p>After this method call, all methods, querying the {@code ChronicleHash}'s entries, {@link
* #longSize()} and {@code size()}), throw {@link ChronicleHashClosedException}. {@link
* #isOpen()} returns {@code false}, {@code close()} itself returns immediately without effects
* (i. e. repetitive {@code close()}, even from concurrent threads, are safe).
* #longSize()} and {@code size()}), throw {@link ChronicleHashClosedException}. {@link #isOpen()} returns {@code false}, {@code close()} itself
* returns immediately without effects (i. e. repetitive {@code close()}, even from concurrent threads, are safe).
*/
@Override
void close();
@@ -16,7 +16,7 @@
package net.openhft.chronicle.hash;
import net.openhft.chronicle.core.io.Closeable;
import net.openhft.chronicle.core.io.DefaultCloseable;
import java.util.function.Consumer;
import java.util.function.Predicate;
@@ -28,12 +28,11 @@ import java.util.function.Predicate;
* @param <E> the entry type
* @see ChronicleHash#segmentContext(int)
*/
public interface HashSegmentContext<K, E extends HashEntry<K>> extends HashContext<K>, Closeable {
public interface HashSegmentContext<K, E extends HashEntry<K>> extends HashContext<K>, DefaultCloseable {
/**
* Performs the given action for each <i>present</i> entry in this segment until all entries
* have been processed or the action throws an {@code Exception}. Exceptions thrown by the
* action are relayed to the caller.
* Performs the given action for each <i>present</i> entry in this segment until all entries have been processed or the action throws an {@code
* Exception}. Exceptions thrown by the action are relayed to the caller.
*
* @param action the action to be performed for each entry in this segment
*/
@@ -16,7 +16,7 @@
package net.openhft.chronicle.map;
import net.openhft.chronicle.core.io.Closeable;
import net.openhft.chronicle.core.io.DefaultCloseable;
import net.openhft.chronicle.hash.ChronicleHashBuilderPrivateAPI;
import net.openhft.chronicle.hash.ReplicatedHashSegmentContext;
import net.openhft.chronicle.hash.replication.ReplicableEntry;
@@ -34,14 +34,13 @@ import static net.openhft.chronicle.hash.replication.TimeProvider.currentTime;
import static net.openhft.chronicle.hash.replication.TimeProvider.systemTimeIntervalBetween;
class OldDeletedEntriesCleanupThread extends Thread
implements Closeable, Predicate<ReplicableEntry> {
implements DefaultCloseable, Predicate<ReplicableEntry> {
private static final Logger LOG = LoggerFactory.getLogger(OldDeletedEntriesCleanupThread.class);
/**
* Don't store a strong ref to a map in order to avoid it's leaking, if the user forgets to
* close() map, from where this thread is shut down explicitly. Dereference map within
* a single method, {@link #cleanupSegment()}. The map has a chance to be collected by GC when
* this thread is sleeping after cleaning up a segment.
* Don't store a strong ref to a map in order to avoid it's leaking, if the user forgets to close() map, from where this thread is shut down
* explicitly. Dereference map within a single method, {@link #cleanupSegment()}. The map has a chance to be collected by GC when this thread is
* sleeping after cleaning up a segment.
*/
private final WeakReference<ReplicatedChronicleMap<?, ?, ?>> mapRef;
/**
@@ -22,7 +22,6 @@ import net.openhft.chronicle.bytes.Bytes;
import net.openhft.chronicle.bytes.BytesStore;
import net.openhft.chronicle.bytes.PointerBytesStore;
import net.openhft.chronicle.core.Jvm;
import net.openhft.chronicle.core.io.Closeable;
import net.openhft.chronicle.hash.ChronicleHashClosedException;
import net.openhft.chronicle.hash.ChronicleHashCorruption;
import net.openhft.chronicle.hash.Data;
@@ -88,9 +87,8 @@ public class VanillaChronicleMap<K, V, R>
/////////////////////////////////////////////////
private transient String name;
/**
* identityString is initialized lazily in {@link #toIdentityString()} rather than in
* {@link #initOwnTransients()} because it depends on {@link #file()} which is set after
* initOwnTransients().
* identityString is initialized lazily in {@link #toIdentityString()} rather than in {@link #initOwnTransients()} because it depends on {@link
* #file()} which is set after initOwnTransients().
*/
private transient String identityString;
private transient boolean defaultEntryOperationsAndMethods;
@@ -131,7 +129,7 @@ public class VanillaChronicleMap<K, V, R>
alignment = wireIn.read(() -> "alignment").int32();
worstAlignment = wireIn.read(() -> "worstAlignment").int32();
maxBloatFactor = wireIn.read(() -> "maxBloatFactor").float64();
maxBloatFactor = wireIn.read(() -> "maxBloatFactor").float64();
}
@Override
@@ -279,7 +277,7 @@ public class VanillaChronicleMap<K, V, R>
@NotNull
@Override
public final Closeable acquireContext(K key, V usingValue) {
public final MapClosable acquireContext(K key, V usingValue) {
QueryContextInterface<K, V, R> q = queryContext(key);
// TODO optimize to update lock in certain cases
try {
@@ -17,10 +17,10 @@
package net.openhft.chronicle.map.impl;
import net.openhft.chronicle.bytes.BytesStore;
import net.openhft.chronicle.core.io.Closeable;
import net.openhft.chronicle.hash.Data;
import net.openhft.chronicle.hash.serialization.DataAccess;
import net.openhft.chronicle.map.ExternalMapQueryContext;
import net.openhft.chronicle.map.MapClosable;
import net.openhft.chronicle.map.impl.ret.InstanceReturnValue;
import net.openhft.chronicle.map.impl.ret.UsableReturnValue;
@@ -38,7 +38,7 @@ public interface QueryContextInterface<K, V, R> extends ExternalMapQueryContext<
DataAccess<V> inputValueDataAccess();
Closeable acquireHandle();
MapClosable acquireHandle();
void initSegmentIndex(int segmentIndex);
@@ -16,14 +16,14 @@
package net.openhft.chronicle.map.impl.stage.query;
import net.openhft.chronicle.core.io.Closeable;
import net.openhft.chronicle.hash.impl.stage.hash.CheckOnEachPublicOperation;
import net.openhft.chronicle.map.MapClosable;
import net.openhft.chronicle.map.impl.stage.ret.UsingReturnValue;
import net.openhft.sg.StageRef;
import net.openhft.sg.Staged;
@Staged
public class AcquireHandle<K, V> implements Closeable {
public class AcquireHandle<K, V> implements MapClosable {
@StageRef
CheckOnEachPublicOperation checkOnEachPublicOperation;