keyClass();
+ /**
+ * @return Type as a Class or UnresolvedType if unknown.
+ */
+ Type keyType();
+
/**
* Returns a context to perform arbitrary operations with the given key in this store.
* Conventionally, should be used in a try-with-resources block: {@code
diff --git a/src/main/java/net/openhft/chronicle/hash/impl/VanillaChronicleHash.java b/src/main/java/net/openhft/chronicle/hash/impl/VanillaChronicleHash.java
index 1b35b95a2..1d613653b 100755
--- a/src/main/java/net/openhft/chronicle/hash/impl/VanillaChronicleHash.java
+++ b/src/main/java/net/openhft/chronicle/hash/impl/VanillaChronicleHash.java
@@ -38,6 +38,7 @@ import net.openhft.chronicle.map.ChronicleMapBuilder;
import net.openhft.chronicle.values.Values;
import net.openhft.chronicle.wire.Marshallable;
import net.openhft.chronicle.wire.WireIn;
+import net.openhft.chronicle.wire.WireInternal;
import net.openhft.chronicle.wire.WireOut;
import org.jetbrains.annotations.NotNull;
@@ -46,6 +47,7 @@ import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.lang.ref.WeakReference;
+import java.lang.reflect.Type;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
@@ -93,7 +95,7 @@ public abstract class VanillaChronicleHash keyClass;
+ public Type keyClass;
public SizeMarshaller keySizeMarshaller;
public SizedReader keyReader;
public DataAccess keyDataAccess;
@@ -247,7 +249,7 @@ public abstract class VanillaChronicleHash "keyClass").typeLiteral();
+ keyClass = wireIn.read(() -> "keyClass").lenientTypeLiteral();
keySizeMarshaller = wireIn.read(() -> "keySizeMarshaller").object(SizeMarshaller.class);
keyReader = wireIn.read(() -> "keyReader").object(SizedReader.class);
keyDataAccess = wireIn.read(() -> "keyDataAccess").object(DataAccess.class);
@@ -682,8 +684,10 @@ public abstract class VanillaChronicleHash keyClass = keyClass();
if (!keyClass.isInstance(key)) {
- // key.getClass will cause NPE exactly as needed
+ if (key == null)
+ throw new NullPointerException("null key not supported");
throw new ClassCastException(toIdentityString() + ": Key must be a " +
keyClass.getName() + " but was a " + key.getClass());
}
diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/ByteableDataAccess.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/ByteableDataAccess.java
index 4f98486ad..e417cbecd 100644
--- a/src/main/java/net/openhft/chronicle/hash/serialization/impl/ByteableDataAccess.java
+++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/ByteableDataAccess.java
@@ -23,6 +23,8 @@ import net.openhft.chronicle.hash.serialization.DataAccess;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import java.lang.reflect.Type;
+
public class ByteableDataAccess extends InstanceCreatingMarshaller
implements DataAccess, Data {
@@ -31,7 +33,7 @@ public class ByteableDataAccess extends InstanceCreatingMars
*/
private transient T instance;
- public ByteableDataAccess(Class tClass) {
+ public ByteableDataAccess(Type tClass) {
super(tClass);
}
@@ -91,6 +93,6 @@ public class ByteableDataAccess extends InstanceCreatingMars
@Override
public DataAccess copy() {
- return new ByteableDataAccess<>(tClass());
+ return new ByteableDataAccess<>(tType());
}
}
diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/BytesMarshallableDataAccess.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/BytesMarshallableDataAccess.java
index ef7598fdd..ee2d02452 100644
--- a/src/main/java/net/openhft/chronicle/hash/serialization/impl/BytesMarshallableDataAccess.java
+++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/BytesMarshallableDataAccess.java
@@ -23,6 +23,8 @@ import net.openhft.chronicle.wire.WireIn;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import java.lang.reflect.Type;
+
import static net.openhft.chronicle.hash.serialization.impl.DefaultElasticBytes.DEFAULT_BYTES_CAPACITY;
public class BytesMarshallableDataAccess
@@ -42,7 +44,7 @@ public class BytesMarshallableDataAccess
this(tClass, DEFAULT_BYTES_CAPACITY);
}
- private BytesMarshallableDataAccess(Class tClass, long bytesCapacity) {
+ private BytesMarshallableDataAccess(Type tClass, long bytesCapacity) {
super(tClass);
initTransients(bytesCapacity);
}
@@ -140,6 +142,6 @@ public class BytesMarshallableDataAccess
@Override
public DataAccess copy() {
- return new BytesMarshallableDataAccess<>(tClass(), bytes.realCapacity());
+ return new BytesMarshallableDataAccess<>(tType(), bytes.realCapacity());
}
}
diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/ExternalBytesMarshallableDataAccess.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/ExternalBytesMarshallableDataAccess.java
index 000183c7f..6f8f8f877 100644
--- a/src/main/java/net/openhft/chronicle/hash/serialization/impl/ExternalBytesMarshallableDataAccess.java
+++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/ExternalBytesMarshallableDataAccess.java
@@ -27,6 +27,8 @@ import net.openhft.chronicle.wire.WireOut;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import java.lang.reflect.Type;
+
import static net.openhft.chronicle.hash.serialization.StatefulCopyable.copyIfNeeded;
import static net.openhft.chronicle.hash.serialization.impl.DefaultElasticBytes.DEFAULT_BYTES_CAPACITY;
@@ -53,7 +55,7 @@ public class ExternalBytesMarshallableDataAccess extends InstanceCreatingMars
}
private ExternalBytesMarshallableDataAccess(
- Class tClass, SizedReader reader, BytesWriter super T> writer,
+ Type tClass, SizedReader reader, BytesWriter super T> writer,
long bytesCapacity) {
super(tClass);
this.writer = writer;
@@ -125,7 +127,7 @@ public class ExternalBytesMarshallableDataAccess extends InstanceCreatingMars
@Override
public DataAccess copy() {
return new ExternalBytesMarshallableDataAccess<>(
- tClass(), copyIfNeeded(reader), copyIfNeeded(writer), bytes.realCapacity());
+ tType(), copyIfNeeded(reader), copyIfNeeded(writer), bytes.realCapacity());
}
@Override
diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/InstanceCreatingMarshaller.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/InstanceCreatingMarshaller.java
index 7dd822762..2d623495c 100644
--- a/src/main/java/net/openhft/chronicle/hash/serialization/impl/InstanceCreatingMarshaller.java
+++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/InstanceCreatingMarshaller.java
@@ -26,6 +26,8 @@ import net.openhft.chronicle.wire.WireIn;
import net.openhft.chronicle.wire.WireOut;
import org.jetbrains.annotations.NotNull;
+import java.lang.reflect.Type;
+
/**
* Holds new instance creation logic, common for many {@link DataAccess} and {@link SizedReader}
* implementations
@@ -34,7 +36,7 @@ import org.jetbrains.annotations.NotNull;
*/
public abstract class InstanceCreatingMarshaller implements Marshallable {
- private Class tClass;
+ private Type tClass;
/**
* Constructor for use in subclasses.
@@ -45,11 +47,19 @@ public abstract class InstanceCreatingMarshaller implements Marshallable {
this.tClass = tClass;
}
+ protected InstanceCreatingMarshaller(Type tClass) {
+ this.tClass = tClass;
+ }
+
/**
* Returns the class of objects deserialized.
*/
protected Class tClass() {
- return tClass;
+ return (Class) tClass;
+ }
+
+ protected Type tType() {
+ return tClass;
}
/**
@@ -63,7 +73,7 @@ public abstract class InstanceCreatingMarshaller implements Marshallable {
*/
protected T createInstance() {
try {
- return ObjectUtils.newInstance(tClass);
+ return ObjectUtils.newInstance(tClass());
} catch (Exception e) {
throw new IllegalStateException("Some of default marshallers, chosen for the type\n" +
tClass + " by default, delegate to \n" +
@@ -80,7 +90,7 @@ public abstract class InstanceCreatingMarshaller implements Marshallable {
@Override
public void readMarshallable(@NotNull WireIn wireIn) {
//noinspection unchecked
- tClass = wireIn.read(() -> "tClass").typeLiteral();
+ tClass = wireIn.read(() -> "tClass").lenientTypeLiteral();
}
@Override
diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/NotReusingSizedMarshallableDataAccess.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/NotReusingSizedMarshallableDataAccess.java
index 82e655804..83f4bbd47 100644
--- a/src/main/java/net/openhft/chronicle/hash/serialization/impl/NotReusingSizedMarshallableDataAccess.java
+++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/NotReusingSizedMarshallableDataAccess.java
@@ -20,13 +20,16 @@ import net.openhft.chronicle.hash.serialization.DataAccess;
import net.openhft.chronicle.hash.serialization.SizedReader;
import net.openhft.chronicle.hash.serialization.SizedWriter;
+import java.lang.reflect.Type;
+
import static net.openhft.chronicle.hash.serialization.StatefulCopyable.copyIfNeeded;
+import static net.openhft.chronicle.hash.serialization.impl.DefaultElasticBytes.DEFAULT_BYTES_CAPACITY;
public class NotReusingSizedMarshallableDataAccess extends SizedMarshallableDataAccess {
public NotReusingSizedMarshallableDataAccess(
- Class tClass, SizedReader sizedReader, SizedWriter super T> sizedWriter) {
- super(tClass, sizedReader, sizedWriter);
+ Type tClass, SizedReader sizedReader, SizedWriter super T> sizedWriter) {
+ super(tClass, sizedReader, sizedWriter, DEFAULT_BYTES_CAPACITY);
}
@Override
@@ -37,6 +40,6 @@ public class NotReusingSizedMarshallableDataAccess extends SizedMarshallableD
@Override
public DataAccess copy() {
return new NotReusingSizedMarshallableDataAccess<>(
- tClass(), copyIfNeeded(sizedReader()), copyIfNeeded(sizedWriter()));
+ tType(), copyIfNeeded(sizedReader()), copyIfNeeded(sizedWriter()));
}
}
diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/SizedMarshallableDataAccess.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/SizedMarshallableDataAccess.java
index 623d00c8c..57b790df3 100644
--- a/src/main/java/net/openhft/chronicle/hash/serialization/impl/SizedMarshallableDataAccess.java
+++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/SizedMarshallableDataAccess.java
@@ -26,6 +26,8 @@ import net.openhft.chronicle.wire.WireOut;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import java.lang.reflect.Type;
+
import static net.openhft.chronicle.hash.serialization.StatefulCopyable.copyIfNeeded;
import static net.openhft.chronicle.hash.serialization.impl.DefaultElasticBytes.DEFAULT_BYTES_CAPACITY;
@@ -52,8 +54,8 @@ public class SizedMarshallableDataAccess extends InstanceCreatingMarshaller tClass, SizedReader sizedReader, SizedWriter super T> sizedWriter,
+ protected SizedMarshallableDataAccess(
+ Type tClass, SizedReader sizedReader, SizedWriter super T> sizedWriter,
long bytesCapacity) {
super(tClass);
this.sizedWriter = sizedWriter;
@@ -151,15 +153,15 @@ public class SizedMarshallableDataAccess extends InstanceCreatingMarshaller copy() {
return new SizedMarshallableDataAccess<>(
- tClass(), copyIfNeeded(sizedReader), copyIfNeeded(sizedWriter),
+ tType(), copyIfNeeded(sizedReader), copyIfNeeded(sizedWriter),
bytes.realCapacity());
}
@Override
public void readMarshallable(@NotNull WireIn wireIn) {
super.readMarshallable(wireIn);
- sizedReader = wireIn.read(() -> "sizedReader").typedMarshallable();
- sizedWriter = wireIn.read(() -> "sizedWriter").typedMarshallable();
+ sizedReader = wireIn.read(() -> "sizedReader").object(SizedReader.class);
+ sizedWriter = wireIn.read(() -> "sizedWriter").object(SizedWriter.class);
initTransients(DEFAULT_BYTES_CAPACITY);
}
diff --git a/src/main/java/net/openhft/chronicle/map/ChronicleMap.java b/src/main/java/net/openhft/chronicle/map/ChronicleMap.java
index c54ef22dc..6618dc2ac 100755
--- a/src/main/java/net/openhft/chronicle/map/ChronicleMap.java
+++ b/src/main/java/net/openhft/chronicle/map/ChronicleMap.java
@@ -27,6 +27,7 @@ import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.io.Serializable;
+import java.lang.reflect.Type;
import java.util.Map;
import java.util.concurrent.ConcurrentMap;
@@ -207,5 +208,10 @@ public interface ChronicleMap extends ConcurrentMap,
* @return the class of {@code }
*/
Class valueClass();
+
+ /**
+ * @return the value Class or UnresolvedType if unknown.
+ */
+ Type valueType();
}
diff --git a/src/main/java/net/openhft/chronicle/map/VanillaChronicleMap.java b/src/main/java/net/openhft/chronicle/map/VanillaChronicleMap.java
index c4b034353..78d93b377 100755
--- a/src/main/java/net/openhft/chronicle/map/VanillaChronicleMap.java
+++ b/src/main/java/net/openhft/chronicle/map/VanillaChronicleMap.java
@@ -44,6 +44,7 @@ import org.jetbrains.annotations.NotNull;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
+import java.lang.reflect.Type;
import java.util.Set;
import java.util.function.BiFunction;
import java.util.function.Function;
@@ -73,7 +74,7 @@ public class VanillaChronicleMap
public transient DefaultValueProvider defaultValueProvider;
/////////////////////////////////////////////////
// Value Data model
- Class valueClass;
+ Type valueClass;
/////////////////////////////////////////////////
// Behavior
transient boolean putReturnsNull;
@@ -116,7 +117,7 @@ public class VanillaChronicleMap
protected void readMarshallableFields(@NotNull WireIn wireIn) {
super.readMarshallableFields(wireIn);
- valueClass = wireIn.read(() -> "valueClass").typeLiteral();
+ valueClass = wireIn.read(() -> "valueClass").lenientTypeLiteral();
valueSizeMarshaller = wireIn.read(() -> "valueSizeMarshaller").object(SizeMarshaller.class);
valueReader = wireIn.read(() -> "valueReader").object(SizedReader.class);
valueDataAccess = wireIn.read(() -> "valueDataAccess").object(DataAccess.class);
@@ -185,6 +186,7 @@ public class VanillaChronicleMap
}
public final V checkValue(Object value) {
+ Class valueClass = valueClass();
if (!valueClass.isInstance(value)) {
throw new ClassCastException(toIdentityString() + ": Value must be a " +
valueClass.getName() + " but was a " + value.getClass());
@@ -206,11 +208,21 @@ public class VanillaChronicleMap
@Override
public Class keyClass() {
+ return (Class) keyClass;
+ }
+
+ @Override
+ public Type keyType() {
return keyClass;
}
@Override
public Class valueClass() {
+ return (Class) valueClass;
+ }
+
+ @Override
+ public Type valueType() {
return valueClass;
}
diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/data/bytes/EntryValueBytesData.java b/src/main/java/net/openhft/chronicle/map/impl/stage/data/bytes/EntryValueBytesData.java
index 0e89384d7..4d5e0322f 100644
--- a/src/main/java/net/openhft/chronicle/map/impl/stage/data/bytes/EntryValueBytesData.java
+++ b/src/main/java/net/openhft/chronicle/map/impl/stage/data/bytes/EntryValueBytesData.java
@@ -44,7 +44,7 @@ public class EntryValueBytesData extends AbstractData {
@Stage("CachedEntryValue")
private V cachedEntryValue =
- mh.m().valueClass() == CharSequence.class ? (V) new StringBuilder() : null;
+ mh.m().valueType() == CharSequence.class ? (V) new StringBuilder() : null;
@Stage("CachedEntryValue")
private boolean cachedEntryValueRead = false;
diff --git a/src/main/java/net/openhft/chronicle/set/SetFromMap.java b/src/main/java/net/openhft/chronicle/set/SetFromMap.java
index 360d3db8e..c31204622 100644
--- a/src/main/java/net/openhft/chronicle/set/SetFromMap.java
+++ b/src/main/java/net/openhft/chronicle/set/SetFromMap.java
@@ -24,6 +24,7 @@ import net.openhft.chronicle.map.VanillaChronicleMap;
import org.jetbrains.annotations.NotNull;
import java.io.File;
+import java.lang.reflect.Type;
import java.util.AbstractSet;
import java.util.Collection;
import java.util.Iterator;
@@ -134,6 +135,11 @@ class SetFromMap extends AbstractSet implements ChronicleSet {
return m.keyClass();
}
+ @Override
+ public Type keyType() {
+ return m.keyType();
+ }
+
// TODO test queryContext methods
@NotNull
diff --git a/src/test/java/net/openhft/chronicle/map/ReplicationCheckingMap.java b/src/test/java/net/openhft/chronicle/map/ReplicationCheckingMap.java
index 046036461..910662f8d 100644
--- a/src/test/java/net/openhft/chronicle/map/ReplicationCheckingMap.java
+++ b/src/test/java/net/openhft/chronicle/map/ReplicationCheckingMap.java
@@ -24,6 +24,7 @@ import org.jetbrains.annotations.NotNull;
import org.junit.Assert;
import java.io.File;
+import java.lang.reflect.Type;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
@@ -243,6 +244,11 @@ public class ReplicationCheckingMap implements ChronicleMap {
return map1.keyClass();
}
+ @Override
+ public Type keyType() {
+ return map1.keyType();
+ }
+
@Override
public boolean forEachEntryWhile(Predicate super MapEntry> predicate) {
return map1.forEachEntryWhile(predicate);
@@ -258,6 +264,11 @@ public class ReplicationCheckingMap implements ChronicleMap {
return map1.valueClass();
}
+ @Override
+ public Type valueType() {
+ return map1.valueType();
+ }
+
@Override
public V acquireUsing(@NotNull K key, V usingValue) {
return map1.acquireUsing(key, usingValue);
diff --git a/src/test/java/net/openhft/chronicle/map/watcher/MapFileClassifier.java b/src/test/java/net/openhft/chronicle/map/watcher/MapFileClassifier.java
new file mode 100644
index 000000000..47be9776c
--- /dev/null
+++ b/src/test/java/net/openhft/chronicle/map/watcher/MapFileClassifier.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2016-2019 Chronicle Software Ltd
+ */
+
+package net.openhft.chronicle.map.watcher;
+
+import net.openhft.chronicle.core.watcher.FileClassifier;
+import net.openhft.chronicle.core.watcher.FileManager;
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+public class MapFileClassifier implements FileClassifier {
+ @Override
+ public FileManager classify(String base, String relative) {
+ Path path = Paths.get(base, relative);
+ if (Files.isRegularFile(path) && relative.endsWith(".cmap")) {
+ return new MapFileManager(base, relative);
+ }
+ return null;
+ }
+}
diff --git a/src/test/java/net/openhft/chronicle/map/watcher/MapFileManager.java b/src/test/java/net/openhft/chronicle/map/watcher/MapFileManager.java
new file mode 100755
index 000000000..63fc2c33c
--- /dev/null
+++ b/src/test/java/net/openhft/chronicle/map/watcher/MapFileManager.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2016-2019 Chronicle Software Ltd
+ */
+
+package net.openhft.chronicle.map.watcher;
+
+import net.openhft.chronicle.bytes.MappedBytes;
+import net.openhft.chronicle.bytes.MappedFile;
+import net.openhft.chronicle.core.Jvm;
+import net.openhft.chronicle.core.watcher.JMXFileManager;
+import net.openhft.chronicle.hash.impl.PersistedChronicleHashResources;
+import net.openhft.chronicle.hash.impl.SizePrefixedBlob;
+import net.openhft.chronicle.map.VanillaChronicleMap;
+import net.openhft.chronicle.wire.ReadAnyWire;
+import net.openhft.chronicle.wire.Wires;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.lang.reflect.Type;
+import java.nio.file.Paths;
+
+public class MapFileManager extends JMXFileManager implements MapFileManagerMBean {
+ private static final long TIME_OUT = 5_000;
+ private String header;
+ private Type keyClass;
+ private Type valueClass;
+ private long size;
+ private String name;
+ private long dataStoreSize;
+ private int segments;
+
+ public MapFileManager(String basePath, String relativePath) {
+ super(basePath, relativePath);
+ }
+
+ @Override
+ protected String type() {
+ return "maps";
+ }
+
+ private long lastUpdate = 0;
+
+ public String getHeader() {
+ update();
+ return header;
+ }
+
+ public String getKeyClass() {
+ return ""+keyClass;
+ }
+
+ public String getValueClass() {
+ return ""+valueClass;
+ }
+
+ public long getSize() {
+ return size;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public long getDataStoreSize() {
+ return dataStoreSize;
+ }
+
+ public int getSegments() {
+ return segments;
+ }
+
+ public long getLastUpdate() {
+ return lastUpdate;
+ }
+
+ private void update() {
+ long now = System.currentTimeMillis();
+ if (lastUpdate + TIME_OUT > now)
+ return;
+
+ File file = Paths.get(basePath, relativePath).toFile();
+
+ MappedFile mf;
+ try {
+ mf = MappedFile.mappedFile(file, file.length());
+ } catch (FileNotFoundException e) {
+ Jvm.warn().on(getClass(), e);
+ return;
+ }
+ try (MappedBytes bytes = MappedBytes.mappedBytes(mf)) {
+ int length = bytes.readInt(SizePrefixedBlob.SIZE_WORD_OFFSET);
+ if (!Wires.isReady(length)) {
+ header = "not ready";
+ } else {
+ bytes.readPositionRemaining(SizePrefixedBlob.SIZE_WORD_OFFSET, Wires.lengthOf(length) + 4);
+ header = Wires.fromSizePrefixedBlobs(bytes);
+
+ bytes.readPositionRemaining(SizePrefixedBlob.SELF_BOOTSTRAPPING_HEADER_OFFSET, Wires.lengthOf(length));
+ ReadAnyWire wire = new ReadAnyWire(bytes);
+ VanillaChronicleMap map = wire.getValueIn()
+ .object(VanillaChronicleMap.class);
+ int headerEnd = SizePrefixedBlob.SELF_BOOTSTRAPPING_HEADER_OFFSET + Wires.lengthOf(length);
+ map.initBeforeMapping(file, mf.raf(), headerEnd, false);
+ map.createMappedStoreAndSegments(
+ new PersistedChronicleHashResources(file));
+
+
+ keyClass = map.keyType();
+ valueClass = map.valueType();
+ size = map.longSize();
+ name = map.name();
+ dataStoreSize = map.dataStoreSize();
+ segments = map.segments();
+ }
+ } catch (Exception e) {
+ Jvm.warn().on(getClass(), "Unable to update", e);
+ header = e.toString();
+ } finally {
+ mf.release();
+ assert mf.refCount() == 0;
+ }
+ }
+}
diff --git a/src/test/java/net/openhft/chronicle/map/watcher/MapFileManagerMBean.java b/src/test/java/net/openhft/chronicle/map/watcher/MapFileManagerMBean.java
new file mode 100755
index 000000000..806136ef0
--- /dev/null
+++ b/src/test/java/net/openhft/chronicle/map/watcher/MapFileManagerMBean.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2016-2019 Chronicle Software Ltd
+ */
+
+package net.openhft.chronicle.map.watcher;
+
+import java.lang.reflect.Type;
+import java.util.Set;
+
+@SuppressWarnings("unused")
+public interface MapFileManagerMBean {
+
+ public String getHeader();
+
+ public String getKeyClass();
+
+ public String getValueClass();
+
+// public long getSize();
+
+ public String getName();
+
+ public long getDataStoreSize();
+
+ public int getSegments();
+
+ public long getLastUpdate();
+}
diff --git a/src/test/java/net/openhft/chronicle/map/watcher/MapWatcherMain.java b/src/test/java/net/openhft/chronicle/map/watcher/MapWatcherMain.java
new file mode 100644
index 000000000..395e6ab1d
--- /dev/null
+++ b/src/test/java/net/openhft/chronicle/map/watcher/MapWatcherMain.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2016-2019 Chronicle Software Ltd
+ */
+
+package net.openhft.chronicle.map.watcher;
+
+import io.hawt.embedded.Main;
+import net.openhft.chronicle.core.Jvm;
+import net.openhft.chronicle.core.watcher.ClassifyingWatcherListener;
+import net.openhft.chronicle.core.watcher.FileSystemWatcher;
+
+import java.io.File;
+
+public class MapWatcherMain {
+ public static void main(String[] args) throws Exception {
+ FileSystemWatcher fsw = new FileSystemWatcher();
+ String absolutePath = new File(".").getAbsolutePath();
+ System.out.println("Watching " + absolutePath);
+ fsw.addPath(absolutePath);
+ ClassifyingWatcherListener listener = new ClassifyingWatcherListener();
+ listener.addClassifier(new MapFileClassifier());
+ fsw.addListener(listener);
+ fsw.start();
+
+ System.setProperty("hawtio.authenticationEnabled", "false");
+ Main main = new Main();
+ main.setWar(Jvm.userHome() +"/OpenHFT/hawtio-default-2.7.1.war");
+ main.run();
+ }
+}