diff --git a/src/main/java/net/openhft/chronicle/ChronicleHash.java b/src/main/java/net/openhft/chronicle/ChronicleHash.java new file mode 100644 index 000000000..996213937 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/ChronicleHash.java @@ -0,0 +1,64 @@ +/* + * Copyright 2014 Higher Frequency Trading http://www.higherfrequencytrading.com + * + * 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 net.openhft.chronicle; + +import net.openhft.chronicle.map.ChronicleMap; +import net.openhft.chronicle.set.ChronicleSet; + +import java.io.Closeable; +import java.io.File; +import java.io.IOException; + +/** + * This interface defines common {@link ChronicleMap} and {@link ChronicleSet}, related to off-heap + * memory management and file-mapping. Not usable by itself. + */ +public interface ChronicleHash extends Closeable { + /** + * 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 + * @see ChronicleHashBuilder#create(File) + * @see ChronicleHashBuilder#create() + */ + File file(); + + /** + * 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 operation system level. I. e. this method call doesn't affect + * other {@link ChronicleMap} or {@link ChronicleSet} instances mapping the same data. + * + *
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. + * + *
+ * TODO what about commit guarantees, when ChronicleMap is used with memory-mapped files, if + * {@code ChronicleMap}/{@code ChronicleSet} closed/not? + * + *
After this method call behaviour of all methods of {@code ChronicleMap}
+ * or {@code ChronicleSet} is undefined. Any method call on the map might throw
+ * any exception, or even JVM crash. Shortly speaking, don't call use map closing.
+ */
+ @Override
+ void close() throws IOException;
+}
diff --git a/src/main/java/net/openhft/chronicle/ChronicleHashBuilder.java b/src/main/java/net/openhft/chronicle/ChronicleHashBuilder.java
index c37ea2cda..505d9614b 100644
--- a/src/main/java/net/openhft/chronicle/ChronicleHashBuilder.java
+++ b/src/main/java/net/openhft/chronicle/ChronicleHashBuilder.java
@@ -1,6 +1,7 @@
package net.openhft.chronicle;
import net.openhft.chronicle.map.*;
+import net.openhft.chronicle.set.ChronicleSet;
import net.openhft.chronicle.set.ChronicleSetBuilder;
import org.jetbrains.annotations.NotNull;
@@ -26,8 +27,8 @@ import java.util.concurrent.TimeUnit;
* @param the concrete builder type, i. e. {@link ChronicleMapBuilder}
* or {@link ChronicleSetBuilder}
*/
-public interface ChronicleHashBuilder For information on
+ * Functionally this interface defines some methods supporting garbage-free off-heap programming:
+ * {@link #getUsing(Object, Object)}, {@link #acquireUsing(Object, Object)}.
+ *
+ * Note that {@code ChronicleMap} extends {@link Closeable}, don't forget
+ * to {@linkplain #close() close} map when it is no longer needed.
+ *
+ * @param If the specified key if absent in the map, {@linkplain
+ * ChronicleMapBuilder#defaultValue(Object) default value} is taken or {@linkplain
+ * ChronicleMapBuilder#defaultValueProvider(DefaultValueProvider) default value provider}
+ * is called (depending on what was configured last in {@code ChronicleMapBuilder}).
+ * If it results to something different from {@code null}, this object is put to this map for
+ * the specified key, and then returned from this {@code get()} call. Otherwise, if default
+ * value is {@code null} and default value provider returns {@code null}, the map remains
+ * unchanged and {@code null} is returned.
+ *
+ * If the value class allows reusing, particularly if it is a {@link Byteable} subclass,
+ * consider {@link #getUsing(Object, Object)} method instead of this to reduce garbage creation.
+ *
+ * @param key the key whose associated value is to be returned
+ * @return the value to which the specified key is mapped after this method call,
+ * or {@code null} if no value is mapped
+ * @see #getUsing(Object, Object)
+ */
+ @Override
+ V get(Object key);
+
+ /**
+ * Returns the value to which the specified key is mapped, read to the provided {@code value}
+ * object, if possible, or returns {@code null}, if this map contains no mapping for the key.
+ *
+ * If the specified key is present in the map, the value data is read to the provided
+ * {@code value} object via value marshaller's {@link BytesMarshaller#read(Bytes, Object)
+ * read(Bytes, value)} or value reader's {@link BytesReader#read(Bytes, long, Object)
+ * read(Bytes, size, value)} method, depending on what deserialization strategy is configured
+ * on this map builder. If the value deserializer is able to reuse the given {@code value}
+ * object, calling this method instead of {@link #get(Object)} could help to reduce garbage
+ * creation.
+ *
+ * The provided {@code value} object is allowed to be {@code null}, in this case
+ * {@code map.getUsing(key, null)} call is semantically equivalent to simple
+ * {@code map.get(key)} call.
+ *
+ * If the specified key if absent in the map, {@linkplain
+ * ChronicleMapBuilder#defaultValue(Object) default value} is taken or {@linkplain
+ * ChronicleMapBuilder#defaultValueProvider(DefaultValueProvider) default value provider}
+ * is called. If it results to something different from {@code null}, this object is put
+ * to this map for the specified key, and then a new value is returned from this
+ * {@code getUsing()} call. Otherwise, if default value is {@code null} and default value
+ * provider, if specified, returns {@code null}, the map remains unchanged and {@code null}
+ * is returned. The provided {@code value} is untouched anyway in this case.
+ *
+ * @param key the key whose associated value is to be returned
+ * @param value the object to read value data in, if possible
+ * @return the value mapped to the specified key after this method call, or {@code null} if no
+ * value is mapped
+ * @see #get(Object)
+ * @see ChronicleMapBuilder#valueMarshallerAndFactory(BytesMarshaller, ObjectFactory)
*/
V getUsing(K key, V value);
@@ -41,15 +120,10 @@ public interface ChronicleMap
+ *
+ * see {@link ChronicleMapBuilder} documentation.
+ *
+ *