You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mnemonic.apache.org by ga...@apache.org on 2016/04/05 21:51:51 UTC
[3/7] incubator-mnemonic git commit: MNEMONIC-5 MNEMONIC-6 #resolve
refactored package names
http://git-wip-us.apache.org/repos/asf/incubator-mnemonic/blob/8e83efe5/core/src/main/java/org/apache/mnemonic/BigDataMemAllocator.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/mnemonic/BigDataMemAllocator.java b/core/src/main/java/org/apache/mnemonic/BigDataMemAllocator.java
new file mode 100644
index 0000000..e663540
--- /dev/null
+++ b/core/src/main/java/org/apache/mnemonic/BigDataMemAllocator.java
@@ -0,0 +1,278 @@
+package org.apache.mnemonic;
+
+import java.nio.ByteBuffer;
+
+import org.flowcomputing.commons.resgc.*;
+import org.flowcomputing.commons.primitives.*;
+import org.apache.mnemonic.service.allocatorservice.VolatileMemoryAllocatorService;
+
+/**
+ * manage a big native memory pool through libvmem.so that is provied by Intel nvml library.
+ *
+ *
+ */
+public class BigDataMemAllocator extends CommonAllocator<BigDataMemAllocator> {
+
+ private boolean m_activegc = true;
+ private long m_gctimeout = 100;
+ private long m_nid = -1;
+ private VolatileMemoryAllocatorService m_vmasvc = null;
+
+ /**
+ * Constructor, it initializes and allocate a memory pool from specified uri
+ * location with specified capacity and an allocator service instance.
+ * usually, the uri points to a mounted
+ * memory device or a location of file system.
+ *
+ * @param vmasvc
+ * the volatile memory allocation service instance
+ *
+ * @param capacity
+ * the capacity of memory pool
+ *
+ * @param uri
+ * the location of memory pool will be created
+ *
+ * @param isnew
+ * a place holder, always specify it as true
+ */
+ public BigDataMemAllocator(VolatileMemoryAllocatorService vmasvc, long capacity, String uri, boolean isnew) {
+ assert null != vmasvc : "VolatileMemoryAllocatorService object is null";
+ if (capacity <= 0) {
+ throw new IllegalArgumentException("BigDataMemAllocator cannot be initialized with capacity <= 0.");
+ }
+
+ m_vmasvc = vmasvc;
+ m_nid = m_vmasvc.init(capacity, uri, isnew);
+
+ /**
+ * create a resource collector to release specified bytebuffer that backed
+ * by underlying big memory pool.
+ */
+ m_bufcollector = new ResCollector<MemBufferHolder<BigDataMemAllocator>, ByteBuffer>(
+ new ResReclaim<ByteBuffer>() {
+ @Override
+ public void reclaim(ByteBuffer mres) {
+ boolean cb_reclaimed = false;
+ if (null != m_bufferreclaimer) {
+ cb_reclaimed = m_bufferreclaimer.reclaim(mres, Long.valueOf(mres.capacity()));
+ }
+ if (!cb_reclaimed) {
+ m_vmasvc.destroyByteBuffer(m_nid, mres);
+ mres = null;
+ }
+ }
+ });
+
+ /**
+ * create a resource collector to release specified chunk that backed by
+ * underlying big memory pool.
+ */
+ m_chunkcollector = new ResCollector<MemChunkHolder<BigDataMemAllocator>, Long>(
+ new ResReclaim<Long>() {
+ @Override
+ public void reclaim(Long mres) {
+ // System.out.println(String.format("Reclaim: %X", mres));
+ boolean cb_reclaimed = false;
+ if (null != m_chunkreclaimer) {
+ cb_reclaimed = m_chunkreclaimer.reclaim(mres, null);
+ }
+ if (!cb_reclaimed) {
+ m_vmasvc.free(m_nid, mres);
+ mres = null;
+ }
+ }
+ });
+ }
+
+ /**
+ * enable active garbage collection. the GC will be forced to collect garbages when
+ * there is no more space for current allocation request.
+ *
+ * @param timeout
+ * the timeout is used to yield for GC performing
+ *
+ * @return this allocator
+ */
+ @Override
+ public BigDataMemAllocator enableActiveGC(long timeout) {
+ m_activegc = true;
+ m_gctimeout = timeout;
+ return this;
+ }
+
+ /**
+ * disable active garbage collection.
+ *
+ * @return this allocator
+ */
+ @Override
+ public BigDataMemAllocator disableActiveGC() {
+ m_activegc = false;
+ return this;
+ }
+
+ /**
+ * release the memory pool and close it.
+ *
+ */
+ @Override
+ public void close() {
+ super.close();
+ }
+
+ /**
+ * force to synchronize uncommitted data to backed memory pool
+ * (this is a placeholder).
+ *
+ */
+ @Override
+ public void sync() {
+ }
+
+ /**
+ * re-size a specified chunk on its backed memory pool.
+ *
+ * @param mholder
+ * the holder of memory chunk. it can be
+ * null.
+ *
+ * @param size
+ * specify a new size of memory chunk
+ *
+ * @return the resized memory chunk handler
+ */
+ @Override
+ public MemChunkHolder<BigDataMemAllocator> resizeChunk(MemChunkHolder<BigDataMemAllocator> mholder, long size){
+ MemChunkHolder<BigDataMemAllocator> ret = null;
+ boolean ac = null != mholder.getRefId();
+ if (size > 0) {
+ Long addr = m_vmasvc.reallocate(m_nid, mholder.get(), size, true);
+ if (0 == addr && m_activegc) {
+ forceGC();
+ addr = m_vmasvc.reallocate(m_nid, mholder.get(), size, true);
+ }
+ if (0 != addr) {
+ mholder.clear();
+ mholder.destroy();
+ ret = new MemChunkHolder<BigDataMemAllocator>(this, addr, size);
+ if (ac) {
+ m_chunkcollector.register(ret);
+ }
+ }
+ }
+ return ret;
+ }
+
+ /**
+ * resize a specified buffer on its backed memory pool.
+ *
+ * @param mholder
+ * the holder of memory buffer. it can be
+ * null.
+ *
+ * @param size
+ * specify a new size of memory chunk
+ *
+ * @return the resized memory buffer handler
+ *
+ */
+ @Override
+ public MemBufferHolder<BigDataMemAllocator> resizeBuffer(MemBufferHolder<BigDataMemAllocator> mholder, long size) {
+ MemBufferHolder<BigDataMemAllocator> ret = null;
+ boolean ac = null != mholder.getRefId();
+ if (size > 0) {
+ int bufpos = mholder.get().position();
+ int buflimit = mholder.get().limit();
+ ByteBuffer buf = m_vmasvc.resizeByteBuffer(m_nid, mholder.get(), size);
+ if (null == buf && m_activegc) {
+ forceGC();
+ buf = m_vmasvc.resizeByteBuffer(m_nid, mholder.get(), size);
+ }
+ if (null != buf) {
+ mholder.clear();
+ mholder.destroy();
+ buf.position(bufpos <= size ? bufpos : 0);
+ buf.limit(buflimit <= size ? buflimit : (int)size);
+ ret = new MemBufferHolder<BigDataMemAllocator>(this, buf);
+ if (ac) {
+ m_bufcollector.register(ret);
+ }
+ }
+ }
+ return ret;
+ }
+
+ /**
+ * create a memory chunk that is managed by its holder.
+ *
+ * @param size
+ * specify the size of memory chunk
+ *
+ * @param autoreclaim
+ * specify whether or not to reclaim this
+ * chunk automatically
+ *
+ * @return a holder contains a memory chunk
+ */
+ @Override
+ public MemChunkHolder<BigDataMemAllocator> createChunk(long size, boolean autoreclaim) {
+ MemChunkHolder<BigDataMemAllocator> ret = null;
+ Long addr = m_vmasvc.allocate(m_nid, size, true);
+ if (0 == addr && m_activegc) {
+ forceGC();
+ addr = m_vmasvc.allocate(m_nid, size, true);
+ }
+ if (0 != addr) {
+ ret = new MemChunkHolder<BigDataMemAllocator>(this, addr, size);
+ ret.setCollector(m_chunkcollector);
+ if (autoreclaim) {
+ m_chunkcollector.register(ret);
+ }
+ }
+ return ret;
+ }
+
+ /**
+ * create a memory buffer that is managed by its holder.
+ *
+ * @param size
+ * specify the size of memory buffer
+ *
+ * @param autoreclaim
+ * specify whether or not to reclaim this
+ * buffer automatically
+ *
+ * @return a holder contains a memory buffer
+ */
+ @Override
+ public MemBufferHolder<BigDataMemAllocator> createBuffer(long size, boolean autoreclaim) {
+ MemBufferHolder<BigDataMemAllocator> ret = null;
+ ByteBuffer bb = m_vmasvc.createByteBuffer(m_nid, size);
+ if (null == bb && m_activegc) {
+ forceGC();
+ bb = m_vmasvc.createByteBuffer(m_nid, size);
+ }
+ if (null != bb) {
+ ret = new MemBufferHolder<BigDataMemAllocator>(this, bb);
+ ret.setCollector(m_bufcollector);
+ if (autoreclaim) {
+ m_bufcollector.register(ret);
+ }
+ }
+ return ret;
+ }
+
+ /**
+ * force to perform GC that is used to release unused backed memory
+ * resources.
+ */
+ private void forceGC() {
+ System.gc();
+ try {
+ Thread.sleep(m_gctimeout);
+ } catch (Exception ex) {
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-mnemonic/blob/8e83efe5/core/src/main/java/org/apache/mnemonic/BigDataPMemAllocator.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/mnemonic/BigDataPMemAllocator.java b/core/src/main/java/org/apache/mnemonic/BigDataPMemAllocator.java
new file mode 100644
index 0000000..aac30e3
--- /dev/null
+++ b/core/src/main/java/org/apache/mnemonic/BigDataPMemAllocator.java
@@ -0,0 +1,469 @@
+package org.apache.mnemonic;
+
+import java.nio.ByteBuffer;
+
+import org.flowcomputing.commons.resgc.*;
+import org.flowcomputing.commons.primitives.*;
+import org.apache.mnemonic.service.allocatorservice.NonVolatileMemoryAllocatorService;
+
+/**
+ * manage a big native persistent memory pool through libpmalloc.so provided by pmalloc project.
+ *
+ *
+ */
+public class BigDataPMemAllocator extends CommonPersistAllocator<BigDataPMemAllocator> implements PMAddressTranslator{
+
+ private boolean m_activegc = true;
+ private long m_gctimeout = 100;
+ private long m_nid = -1;
+ private long b_addr = 0;
+ private NonVolatileMemoryAllocatorService m_nvmasvc = null;
+
+ /**
+ * Constructor, it initializes and allocate a memory pool from specified uri
+ * location with specified capacity and an allocator service instance.
+ * usually, the uri points to a mounted
+ * non-volatile memory device or a location of file system.
+ *
+ * @param nvmasvc
+ * the non-volatile memory allocation service instance
+ *
+ * @param capacity
+ * the capacity of memory pool
+ *
+ * @param uri
+ * the location of memory pool will be created
+ *
+ * @param isnew
+ * a place holder, always specify it as true
+ */
+ public BigDataPMemAllocator(NonVolatileMemoryAllocatorService nvmasvc, long capacity, String uri, boolean isnew) {
+ assert null != nvmasvc : "NonVolatileMemoryAllocatorService object is null";
+ if (capacity <= 0) {
+ throw new IllegalArgumentException("BigDataPMemAllocator cannot be initialized with capacity <= 0.");
+ }
+
+ m_nvmasvc = nvmasvc;
+
+ m_nid = m_nvmasvc.init(capacity, uri, isnew);
+ b_addr = m_nvmasvc.getBaseAddress(m_nid);
+
+ /**
+ * create a resource collector to release specified chunk that backed by
+ * underlying big memory pool.
+ */
+ m_chunkcollector = new ResCollector<MemChunkHolder<BigDataPMemAllocator>, Long>(new ResReclaim<Long>() {
+ @Override
+ public void reclaim(Long mres) {
+ // System.out.println(String.format("Reclaim: %X", mres));
+ boolean cb_reclaimed = false;
+ if (null != m_chunkreclaimer) {
+ cb_reclaimed = m_chunkreclaimer.reclaim(mres, null);
+ }
+ if (!cb_reclaimed) {
+ m_nvmasvc.free(m_nid, mres);
+ mres = null;
+ }
+ }
+ });
+
+ /**
+ * create a resource collector to release specified bytebuffer that backed
+ * by underlying big memory pool.
+ */
+ m_bufcollector = new ResCollector<MemBufferHolder<BigDataPMemAllocator>, ByteBuffer>(
+ new ResReclaim<ByteBuffer>() {
+ @Override
+ public void reclaim(ByteBuffer mres) {
+ boolean cb_reclaimed = false;
+ if (null != m_bufferreclaimer) {
+ cb_reclaimed = m_bufferreclaimer.reclaim(mres, Long.valueOf(mres.capacity()));
+ }
+ if (!cb_reclaimed) {
+ m_nvmasvc.destroyByteBuffer(m_nid, mres);
+ mres = null;
+ }
+ }
+ });
+ }
+
+ /**
+ * enable active garbage collection. the GC will be forced to collect garbages when
+ * there is no more space for current allocation request.
+ *
+ * @param timeout
+ * the timeout is used to yield for GC performing
+ */
+ @Override
+ public BigDataPMemAllocator enableActiveGC(long timeout) {
+ m_activegc = true;
+ m_gctimeout = timeout;
+ return this;
+ }
+
+ /**
+ * disable active garbage collection.
+ *
+ */
+ @Override
+ public BigDataPMemAllocator disableActiveGC() {
+ m_activegc = false;
+ return this;
+ }
+
+ /**
+ * Release the memory pool and close it.
+ *
+ */
+ @Override
+ public void close() {
+ forceGC();
+ super.close();
+ m_nvmasvc.close(m_nid);
+ }
+
+ /**
+ * force to synchronize uncommitted data to backed memory pool
+ * (this is a placeholder).
+ *
+ */
+ @Override
+ public void sync() {
+ }
+
+ /**
+ * re-size a specified chunk on its backed memory pool.
+ *
+ * @param mholder
+ * the holder of memory chunk. it can be
+ * null.
+ *
+ * @param size
+ * specify a new size of memory chunk
+ *
+ * @return the resized memory chunk handler
+ */
+ @Override
+ public MemChunkHolder<BigDataPMemAllocator> resizeChunk(MemChunkHolder<BigDataPMemAllocator> mholder, long size){
+ MemChunkHolder<BigDataPMemAllocator> ret = null;
+ boolean ac = null != mholder.getRefId();
+ if (size > 0) {
+ Long addr = m_nvmasvc.reallocate(m_nid, mholder.get(), size, true);
+ if (0 == addr && m_activegc) {
+ forceGC();
+ addr = m_nvmasvc.reallocate(m_nid, mholder.get(), size, true);
+ }
+ if (0 != addr) {
+ mholder.clear();
+ mholder.destroy();
+ ret = new MemChunkHolder<BigDataPMemAllocator>(this, addr, size);
+ if (ac) {
+ m_chunkcollector.register(ret);
+ }
+ }
+ }
+ return ret;
+ }
+
+ /**
+ * resize a specified buffer on its backed memory pool.
+ *
+ * @param mholder
+ * the holder of memory buffer. it can be
+ * null.
+ *
+ * @param size
+ * specify a new size of memory chunk
+ *
+ * @return the resized memory buffer handler
+ *
+ */
+ @Override
+ public MemBufferHolder<BigDataPMemAllocator> resizeBuffer(MemBufferHolder<BigDataPMemAllocator> mholder, long size) {
+ MemBufferHolder<BigDataPMemAllocator> ret = null;
+ boolean ac = null != mholder.getRefId();
+ if (size > 0) {
+ int bufpos = mholder.get().position();
+ int buflimit = mholder.get().limit();
+ ByteBuffer buf = m_nvmasvc.resizeByteBuffer(m_nid, mholder.get(), size);
+ if (null == buf && m_activegc) {
+ forceGC();
+ buf = m_nvmasvc.resizeByteBuffer(m_nid, mholder.get(), size);
+ }
+ if (null != buf) {
+ mholder.clear();
+ mholder.destroy();
+ buf.position(bufpos <= size ? bufpos : 0);
+ buf.limit(buflimit <= size ? buflimit : (int)size);
+ ret = new MemBufferHolder<BigDataPMemAllocator>(this, buf);
+ if (ac) {
+ m_bufcollector.register(ret);
+ }
+ }
+ }
+ return ret;
+ }
+
+ /**
+ * create a memory chunk that is managed by its holder.
+ *
+ * @param size
+ * specify the size of memory chunk
+ *
+ * @param autoreclaim
+ * specify whether or not to reclaim this
+ * chunk automatically
+ *
+ * @return a holder contains a memory chunk
+ */
+ @Override
+ public MemChunkHolder<BigDataPMemAllocator> createChunk(long size, boolean autoreclaim) {
+ MemChunkHolder<BigDataPMemAllocator> ret = null;
+ Long addr = m_nvmasvc.allocate(m_nid, size, true);
+ if ((null == addr || 0 == addr) && m_activegc) {
+ forceGC();
+ addr = m_nvmasvc.allocate(m_nid, size, true);
+ }
+ if (null != addr && 0 != addr) {
+ ret = new MemChunkHolder<BigDataPMemAllocator>(this, addr, size);
+ ret.setCollector(m_chunkcollector);
+ if (autoreclaim) {
+ m_chunkcollector.register(ret);
+ }
+ }
+ return ret;
+ }
+
+ /**
+ * create a memory buffer that is managed by its holder.
+ *
+ * @param size
+ * specify the size of memory buffer
+ *
+ * @param autoreclaim
+ * specify whether or not to reclaim this
+ * buffer automatically
+ *
+ * @return a holder contains a memory buffer
+ */
+ @Override
+ public MemBufferHolder<BigDataPMemAllocator> createBuffer(long size, boolean autoreclaim) {
+ MemBufferHolder<BigDataPMemAllocator> ret = null;
+ ByteBuffer bb = m_nvmasvc.createByteBuffer(m_nid, size);
+ if (null == bb && m_activegc) {
+ forceGC();
+ bb = m_nvmasvc.createByteBuffer(m_nid, size);
+ }
+ if (null != bb) {
+ ret = new MemBufferHolder<BigDataPMemAllocator>(this, bb);
+ ret.setCollector(m_bufcollector);
+ if (autoreclaim) {
+ m_bufcollector.register(ret);
+ }
+ }
+ return ret;
+ }
+
+ /**
+ * retrieve a memory buffer from its backed memory allocator.
+ *
+ * @param phandler
+ * specify the handler of memory buffer to retrieve
+ *
+ * @param autoreclaim
+ * specify whether this retrieved memory buffer can be reclaimed automatically or not
+ *
+ * @return a holder contains the retrieved memory buffer
+ */
+ @Override
+ public MemBufferHolder<BigDataPMemAllocator> retrieveBuffer(long phandler, boolean autoreclaim) {
+ MemBufferHolder<BigDataPMemAllocator> ret = null;
+ ByteBuffer bb = m_nvmasvc.retrieveByteBuffer(m_nid, getEffectiveAddress(phandler));
+ if (null != bb) {
+ ret = new MemBufferHolder<BigDataPMemAllocator>(this, bb);
+ if (autoreclaim) {
+ m_bufcollector.register(ret);
+ }
+ }
+ return ret;
+ }
+
+ /**
+ * retrieve a memory chunk from its backed memory allocator.
+ *
+ * @param phandler
+ * specify the handler of memory chunk to retrieve
+ *
+ * @param autoreclaim
+ * specify whether this retrieved memory chunk can be reclaimed automatically or not
+ *
+ * @return a holder contains the retrieved memory chunk
+ */
+ @Override
+ public MemChunkHolder<BigDataPMemAllocator> retrieveChunk(long phandler, boolean autoreclaim) {
+ MemChunkHolder<BigDataPMemAllocator> ret = null;
+ long eaddr = getEffectiveAddress(phandler);
+ long sz = m_nvmasvc.retrieveSize(m_nid, eaddr);
+ if (sz > 0L) {
+ ret = new MemChunkHolder<BigDataPMemAllocator>(this, eaddr, sz);
+ if (autoreclaim) {
+ m_chunkcollector.register(ret);
+ }
+ }
+ return ret;
+ }
+
+ /**
+ * get the handler from a memory buffer holder.
+ *
+ * @param mbuf
+ * specify the memory buffer holder
+ *
+ * @return a handler that could be used to retrieve its memory buffer
+ */
+ @Override
+ public long getBufferHandler(MemBufferHolder<BigDataPMemAllocator> mbuf) {
+ return getPortableAddress(m_nvmasvc.getByteBufferHandler(m_nid, mbuf.get()));
+ }
+
+ /**
+ * get the handler from a memory chunk holder.
+ *
+ * @param mchunk
+ * specify the memory chunk holder
+ *
+ * @return a handler that could be used to retrieve its memory chunk
+ */
+ @Override
+ public long getChunkHandler(MemChunkHolder<BigDataPMemAllocator> mchunk) {
+ return getPortableAddress(mchunk.get());
+ }
+
+ /**
+ * determine whether this allocator supports to store non-volatile handler or not.
+ * (it is a placeholder)
+ *
+ * @return true if there is
+ */
+ @Override
+ public boolean hasNonVolatileHandlerStore() {
+ return true;
+ }
+
+ /**
+ * start a application level transaction on this allocator.
+ * (it is a place holder)
+ *
+ */
+ @Override
+ public void beginTransaction() {
+ throw new UnsupportedOperationException("Transaction Unsupported.");
+ }
+
+ /**
+ * end a application level transaction on this allocator.
+ * (it is a place holder)
+ *
+ */
+ @Override
+ public void endTransaction() {
+ throw new UnsupportedOperationException("Transaction Unsupported.");
+ }
+
+ /**
+ * set a handler on key.
+ *
+ * @param key
+ * the key to set its value
+ *
+ * @param handler
+ * the handler
+ */
+ public void setHandler(long key, long handler) {
+ m_nvmasvc.setHandler(m_nid, key, handler);
+ }
+
+ /**
+ * get a handler value.
+ *
+ * @param key
+ * the key to set its value
+ *
+ * @return the value of handler
+ */
+ public long getHandler(long key) {
+ return m_nvmasvc.getHandler(m_nid, key);
+ }
+
+ /**
+ * return the capacity of non-volatile handler store.
+ *
+ * @return the capacity of handler store
+ *
+ */
+ public long handlerCapacity() {
+ return m_nvmasvc.handlerCapacity(m_nid);
+ }
+
+ /**
+ * force to perform GC that is used to re-claim garbages objects
+ * as well as memory resources managed by this allocator.
+ *
+ */
+ private void forceGC() {
+ System.gc();
+ try {
+ Thread.sleep(m_gctimeout);
+ } catch (Exception ex) {
+ }
+ }
+
+ /**
+ * calculate the portable address
+ *
+ * @param addr
+ * the address to be calculated
+ *
+ * @return the portable address
+ */
+ @Override
+ public long getPortableAddress(long addr) {
+ return addr - b_addr;
+ }
+
+ /**
+ * calculate the effective address
+ *
+ * @param addr
+ * the address to be calculated
+ *
+ * @return the effective address
+ */
+ @Override
+ public long getEffectiveAddress(long addr) {
+ return addr + b_addr;
+ }
+
+ /**
+ * get the base address
+ *
+ * @return the base address
+ */
+ @Override
+ public long getBaseAddress() {
+ return b_addr;
+ }
+
+ /**
+ * set the base address for calculation
+ *
+ * @param addr
+ * the base address
+ *
+ */
+ @Override
+ public long setBaseAddress(long addr) {
+ return b_addr = addr;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-mnemonic/blob/8e83efe5/core/src/main/java/org/apache/mnemonic/ByteBufferBackedInputStream.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/mnemonic/ByteBufferBackedInputStream.java b/core/src/main/java/org/apache/mnemonic/ByteBufferBackedInputStream.java
new file mode 100644
index 0000000..046472b
--- /dev/null
+++ b/core/src/main/java/org/apache/mnemonic/ByteBufferBackedInputStream.java
@@ -0,0 +1,61 @@
+package org.apache.mnemonic;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+
+/**
+ * an input Stream that is backed by a in-memory ByteBuffer.
+ *
+ *
+ */
+public class ByteBufferBackedInputStream extends InputStream {
+
+ private ByteBuffer buf;
+
+ /**
+ * accept a ByteBuffer as backed object for inputStream.
+ *
+ * @param buf
+ * specify a bytebuffer that is where any data is from
+ */
+ public ByteBufferBackedInputStream(ByteBuffer buf) {
+ this.buf = buf;
+ }
+
+ /**
+ * read an integer value from backed ByteBuffer.
+ *
+ * @return a integer value from stream input
+ */
+ public int read() throws IOException {
+ if (!buf.hasRemaining()) {
+ return -1;
+ }
+ return buf.get() & 0xFF;
+ }
+
+ /**
+ * read a specified range of byte array from backed ByteBuffer.
+ *
+ * @param bytes
+ * specify a output byte array to store data
+ *
+ * @param off
+ * specify the offset from ByteBuffer to read
+ *
+ * @param len
+ * specify the length of bytes to read
+ *
+ * @return the number of bytes has been read
+ */
+ public int read(byte[] bytes, int off, int len) throws IOException {
+ if (!buf.hasRemaining()) {
+ return -1;
+ }
+
+ len = Math.min(len, buf.remaining());
+ buf.get(bytes, off, len);
+ return len;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-mnemonic/blob/8e83efe5/core/src/main/java/org/apache/mnemonic/ByteBufferBackedOutputStream.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/mnemonic/ByteBufferBackedOutputStream.java b/core/src/main/java/org/apache/mnemonic/ByteBufferBackedOutputStream.java
new file mode 100644
index 0000000..6755444
--- /dev/null
+++ b/core/src/main/java/org/apache/mnemonic/ByteBufferBackedOutputStream.java
@@ -0,0 +1,56 @@
+package org.apache.mnemonic;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+
+/**
+ * an output Stream that is backed by a in-memory ByteBuffer.
+ *
+ *
+ */
+public class ByteBufferBackedOutputStream extends OutputStream {
+
+ private ByteBuffer buf;
+
+ /**
+ * accept a ByteBuffer to store external data, the capacity of it could be
+ * extended at will.
+ *
+ * @param buf
+ * specify a ByteBuffer object that is used to store external
+ * data to its backed buffer
+ *
+ */
+ public ByteBufferBackedOutputStream(ByteBuffer buf) {
+ this.buf = buf;
+ }
+
+ /**
+ * write an integer value to backed buffer.
+ *
+ * @param b
+ * specify an integer value to be written
+ */
+ public void write(int b) throws IOException {
+ buf.put((byte) b);
+ }
+
+ /**
+ * write an array of bytes to a specified range of backed buffer
+ *
+ * @param bytes
+ * specify a byte array to write
+ *
+ * @param off
+ * specify the offset of backed buffer where is start point to be
+ * written
+ *
+ * @param len
+ * specify the length of bytes to be written
+ */
+ public void write(byte[] bytes, int off, int len) throws IOException {
+ buf.put(bytes, off, len);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-mnemonic/blob/8e83efe5/core/src/main/java/org/apache/mnemonic/ByteBufferSerializer.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/mnemonic/ByteBufferSerializer.java b/core/src/main/java/org/apache/mnemonic/ByteBufferSerializer.java
new file mode 100644
index 0000000..7ed9f05
--- /dev/null
+++ b/core/src/main/java/org/apache/mnemonic/ByteBufferSerializer.java
@@ -0,0 +1,149 @@
+package org.apache.mnemonic;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.nio.ByteBuffer;
+import java.io.InputStream;
+
+/**
+ * a serializer class that manages to serialize any serilizable objects from/to
+ * ByteBuffer.
+ *
+ */
+
+public class ByteBufferSerializer {
+
+ /**
+ * serialize object to a ByteBuffer object.
+ *
+ * @param <ValueT>
+ * the type of object
+ *
+ * @param obj
+ * specify a object that is serializable
+ *
+ * @throws IOException
+ * the exception of serialization
+ *
+ * @return a ByteBuffer object contained serialized object
+ */
+ public static <ValueT> ByteBuffer toByteBuffer(ValueT obj)
+ throws IOException {
+ byte[] bytes = null;
+ ByteArrayOutputStream bos = null;
+ ObjectOutputStream oos = null;
+ try {
+ bos = new ByteArrayOutputStream();
+ oos = new ObjectOutputStream(bos);
+ oos.writeObject(obj);
+ oos.flush();
+ bytes = bos.toByteArray();
+ } finally {
+ if (oos != null) {
+ oos.close();
+ }
+ if (bos != null) {
+ bos.close();
+ }
+ }
+ return ByteBuffer.wrap(bytes);
+ }
+
+ /**
+ * de-serialize an object from a ByteBuffer object.
+ *
+ * @param <ValueT>
+ * the type of object
+ *
+ * @param bf
+ * specify an ByteBuffer contains data that can be de-serialized
+ *
+ * @throws IOException
+ * the exception of deserialization
+ *
+ * @throws ClassNotFoundException
+ * Not found class of de-serialized object
+ *
+ * @return a de-serialized object
+ */
+ @SuppressWarnings("unchecked")
+ public static <ValueT> ValueT toObject(ByteBuffer bf) throws IOException,
+ ClassNotFoundException {
+ Object obj = null;
+ InputStream is = null;
+ ObjectInputStream ois = null;
+ try {
+ is = new ByteBufferBackedInputStream(bf);
+ ois = new ObjectInputStream(is);
+ obj = ois.readObject();
+ } finally {
+ if (is != null) {
+ is.close();
+ }
+ if (ois != null) {
+ ois.close();
+ }
+ }
+ return (ValueT) obj;
+ }
+
+ /**
+ * serialize object to a MemBufferHolder object.
+ *
+ * @param <A> the type of bound allocator
+ *
+ * @param <ValueT>
+ * the type of object
+ *
+ * @param ar
+ * specify an Allocator that is used to generate MemBufferHolder
+ * which is backed by a native memory block
+ *
+ * @param obj
+ * specify a object that is serializable
+ *
+ * @throws IOException
+ * the exception of serialization
+ *
+ * @return a MemBufferHolder object contained serialized object
+ */
+ public static <A extends CommonAllocator<A>, ValueT> MemBufferHolder<A>
+ toMemBufferHolder(A ar, ValueT obj) throws IOException {
+ MemBufferHolder<A> ret = null;
+ ByteBuffer bb = toByteBuffer(obj);
+ if (null != bb && bb.remaining() > 0) {
+ ret = ar.createBuffer(bb.remaining());
+ ret.get().put(bb);
+ ret.get().flip();
+ }
+ return ret;
+ }
+
+ /**
+ * de-serialize an object from a MemBufferHolder object.
+ *
+ * @param <A> the type of bound allocator
+ *
+ * @param <ValueT>
+ * the type of object
+ *
+ * @param mbh
+ * specify an MemBufferHolder who contains data that can be
+ * de-serialized
+ *
+ * @throws IOException
+ * the exception of deserialization
+ *
+ * @throws ClassNotFoundException
+ * Not found class of de-serialized object
+ *
+ * @return a de-serialized object
+ */
+ public static <A extends CommonAllocator<A>, ValueT> ValueT
+ fromMemBufferHolder(MemBufferHolder<A> mbh)
+ throws IOException, ClassNotFoundException {
+ return toObject(mbh.get());
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-mnemonic/blob/8e83efe5/core/src/main/java/org/apache/mnemonic/CachePool.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/mnemonic/CachePool.java b/core/src/main/java/org/apache/mnemonic/CachePool.java
new file mode 100644
index 0000000..8a9af75
--- /dev/null
+++ b/core/src/main/java/org/apache/mnemonic/CachePool.java
@@ -0,0 +1,144 @@
+package org.apache.mnemonic;
+
+import java.util.Set;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * This is a abstract CachePool class that is inherited from LinedHashMap class,
+ * it extends functionalities of its parent class to support some new features
+ * that is usually requried in data caching usage scenario.
+ *
+ *
+ */
+public abstract class CachePool<KeyT, ValueT> extends
+ LinkedHashMap<KeyT, ValueT> {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+
+ public CachePool(int initialCapacity, float loadFactor) {
+ super(initialCapacity, loadFactor);
+ }
+
+ /**
+ * Return available capacity for new entries.
+ *
+ * @return available capacity in this cache pool
+ */
+ public abstract long freeCapacity();
+
+ /**
+ * Return the used capacity of cached entries.
+ *
+ * @return the used size of this cache pool
+ */
+ public abstract long usedCapacity();
+
+ /**
+ * Put an entry in this cache pool and evict eldest entries if necessary
+ * that will free enough space to hold new entry, which entry could be
+ * evicted that can be customized by ({@link EvictFilter}), regarding how
+ * to post-process the eldest entry that can be customized by (
+ * {@link DropEvent}). If this cache pool previously contained an entry for
+ * the key, the old value will be replaced by the specified value
+ *
+ * @param k
+ * the key whoes associated value is to be put
+ *
+ * @param v
+ * the value to be put
+ *
+ * @param fsop
+ * the customized operations to free space to hold new entry
+ *
+ * @param dfilter
+ * the filter of entries for deletion
+ *
+ * @return <tt>true</tt> if the entry has been put into this container
+ *
+ */
+ public abstract ValueT put(KeyT k, ValueT v, DropEvent<KeyT, ValueT> fsop,
+ EvictFilter<KeyT, ValueT> dfilter);
+
+ /**
+ * Put all entries into this cache pool and evict eldes entries if
+ * necessary.
+ *
+ * @param m
+ * the Map object that contains entries to be put
+ *
+ * @param fsop
+ * the customized operations to free space to hold new entry
+ *
+ * @param dfilter
+ * the filter of entries for deletion
+ *
+ */
+ public abstract void putAll(
+ Map<? extends KeyT, ? extends ValueT> m,
+ DropEvent<KeyT, ValueT> fsop,
+ EvictFilter<KeyT, ValueT> dfilter);
+
+ /**
+ * Returns a new {@link Set} view of the keys of this cache pool, It
+ * contains the most recently visited keys
+ *
+ * @param n
+ * the number of keys to retrieve
+ *
+ * @return a set of hot keys
+ */
+ public abstract Set<KeyT> hotKeySet(int n);
+
+ /**
+ * Ensure the free capacity is greater than the specified size
+ *
+ * @param freesz
+ * the size of free capacity that needs to be secured
+ *
+ * @return <tt>true</tt> if the size of free capacity is greater than the
+ * specified size after evacuation
+ *
+ * @see #ensureFreeSpace(long, DropEvent, EvictFilter)
+ */
+ public abstract boolean ensureFreeSpace(long freesz);
+
+ /**
+ * Removes a first qualified entry in this cache pool
+ *
+ * @param fsop
+ * the customized callback to post-process its evicted entry
+ *
+ * @param dfilter
+ * the filter for entry deletion
+ *
+ * @return <tt>true</tt> if there is one qualified entry that has been
+ * dropped
+ */
+ public abstract boolean removeFirstEntry(DropEvent<KeyT, ValueT> fsop,
+ EvictFilter<KeyT, ValueT> dfilter);
+
+ /**
+ * Ensure the size of free capacity is greater than the specified size, the
+ * entries will be filtered by {@link EvictFilter} before dropping, the
+ * {@link DropEvent} is used for post-processing
+ *
+ * @param freesz
+ * the size of free capacity that needs to be secured
+ *
+ * @param fsop
+ * the customized operations to free space to hold new entry
+ *
+ * @param dfilter
+ * the filter of entries for deletion
+ *
+ * @return <tt>true</tt> if the size of free capacity is greater than the
+ * specified size after evication if necessary
+ */
+ public abstract boolean ensureFreeSpace(long freesz,
+ DropEvent<KeyT, ValueT> fsop, EvictFilter<KeyT, ValueT> dfilter);
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-mnemonic/blob/8e83efe5/core/src/main/java/org/apache/mnemonic/CommonAllocator.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/mnemonic/CommonAllocator.java b/core/src/main/java/org/apache/mnemonic/CommonAllocator.java
new file mode 100644
index 0000000..20a584b
--- /dev/null
+++ b/core/src/main/java/org/apache/mnemonic/CommonAllocator.java
@@ -0,0 +1,104 @@
+package org.apache.mnemonic;
+
+import java.nio.ByteBuffer;
+
+import org.flowcomputing.commons.resgc.ResCollector;
+
+/**
+ * an abstract common class for memory allocator to provide common
+ * functionalities.
+ *
+ */
+public abstract class CommonAllocator<A extends CommonAllocator<A>> implements Allocator<A> {
+
+ protected Reclaim<Long> m_chunkreclaimer = null;
+ protected Reclaim<ByteBuffer> m_bufferreclaimer = null;
+
+ protected ResCollector<MemChunkHolder<A>, Long> m_chunkcollector = null;
+ protected ResCollector<MemBufferHolder<A>, ByteBuffer> m_bufcollector = null;
+
+ /**
+ * set a reclaimer to reclaim memory buffer
+ *
+ * @param reclaimer
+ * specify a reclaimer to accept reclaim request
+ */
+ public void setBufferReclaimer(Reclaim<ByteBuffer> reclaimer) {
+ m_bufferreclaimer = reclaimer;
+ }
+
+ /**
+ * set a reclaimer to reclaim memory chunk
+ *
+ * @param reclaimer
+ * specify a reclaimer to accept reclaim request
+ */
+ public void setChunkReclaimer(Reclaim<Long> reclaimer) {
+ m_chunkreclaimer = reclaimer;
+ }
+
+ /**
+ * create a memory chunk that is managed by its holder.
+ *
+ * @param size
+ * specify the size of memory chunk
+ *
+ * @return a holder contains a memory chunk
+ */
+ @Override
+ public MemChunkHolder<A> createChunk(long size) {
+ return createChunk(size, true);
+ }
+
+ /**
+ * create a memory buffer that is managed by its holder.
+ *
+ * @param size
+ * specify the size of memory buffer
+ *
+ * @return a holder contains a memory buffer
+ */
+ @Override
+ public MemBufferHolder<A> createBuffer(long size) {
+ return createBuffer(size, true);
+ }
+
+ /**
+ * register a memory chunk for auto-reclaim
+ *
+ * @param mholder
+ * specify a chunk holder to register
+ */
+ @Override
+ public void registerChunkAutoReclaim(MemChunkHolder<A> mholder) {
+ m_chunkcollector.register(mholder);
+ }
+
+ /**
+ * register a memory buffer for auto-reclaim
+ *
+ * @param mholder
+ * specify a buffer holder to register
+ */
+ @Override
+ public void registerBufferAutoReclaim(MemBufferHolder<A> mholder) {
+ m_bufcollector.register(mholder);
+ }
+
+ /**
+ * close both of resource collectors for this allocator
+ *
+ */
+ @Override
+ public void close() {
+ if (null != m_chunkcollector) {
+ m_chunkcollector.close();
+ m_chunkcollector = null;
+ }
+ if (null != m_bufcollector) {
+ m_bufcollector.close();
+ m_bufcollector = null;
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-mnemonic/blob/8e83efe5/core/src/main/java/org/apache/mnemonic/CommonPersistAllocator.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/mnemonic/CommonPersistAllocator.java b/core/src/main/java/org/apache/mnemonic/CommonPersistAllocator.java
new file mode 100644
index 0000000..6e0374d
--- /dev/null
+++ b/core/src/main/java/org/apache/mnemonic/CommonPersistAllocator.java
@@ -0,0 +1,120 @@
+package org.apache.mnemonic;
+
+/**
+ * an abstract common class for persistent memory allocator to provide common
+ * functionalities.
+ *
+ */
+public abstract class CommonPersistAllocator<A extends CommonAllocator<A>> extends CommonAllocator<A> {
+
+ /**
+ * determine whether the allocator supports transaction feature or not
+ *
+ * @return true if supported
+ */
+ public boolean supportTransaction() {
+ return false;
+ }
+
+ /**
+ * determine whether the allocator does atomic operations on memory pool
+ *
+ * @return true if it is
+ *
+ */
+ public boolean isAtomicOperation() {
+ return false;
+ }
+
+ /**
+ * determine whether this allocator supports to store non-volatile handler or not
+ *
+ * @return true if there is
+ */
+ public boolean hasNonVolatileHandlerStore() {
+ return false;
+ }
+
+ /**
+ * retrieve a memory buffer from its backed memory allocator.
+ *
+ * @param phandler
+ * specify the handler of memory buffer to retrieve
+ *
+ * @return a holder contains the retrieved memory buffer
+ */
+ public MemBufferHolder<A> retrieveBuffer(long phandler) {
+ return retrieveBuffer(phandler, true);
+ }
+
+ /**
+ * retrieve a memory chunk from its backed memory allocator.
+ *
+ * @param phandler
+ * specify the handler of memory chunk to retrieve
+ *
+ * @return a holder contains the retrieved memory chunk
+ */
+ public MemChunkHolder<A> retrieveChunk(long phandler) {
+ return retrieveChunk(phandler, true);
+ }
+
+ /**
+ * retrieve a memory buffer from its backed memory allocator.
+ *
+ * @param phandler
+ * specify the handler of memory buffer to retrieve
+ *
+ * @param autoreclaim
+ * specify whether this retrieved memory buffer can be reclaimed automatically or not
+ *
+ * @return a holder contains the retrieved memory buffer
+ */
+ abstract public MemBufferHolder<A> retrieveBuffer(long phandler, boolean autoreclaim);
+
+ /**
+ * retrieve a memory chunk from its backed memory allocator.
+ *
+ * @param phandler
+ * specify the handler of memory chunk to retrieve
+ *
+ * @param autoreclaim
+ * specify whether this retrieved memory chunk can be reclaimed automatically or not
+ *
+ * @return a holder contains the retrieved memory chunk
+ */
+ abstract public MemChunkHolder<A> retrieveChunk(long phandler, boolean autoreclaim);
+
+ /**
+ * get the handler from a memory buffer holder.
+ *
+ * @param mbuf
+ * specify the memory buffer holder
+ *
+ * @return a handler that could be used to retrieve its memory buffer
+ */
+ abstract public long getBufferHandler(MemBufferHolder<A> mbuf);
+
+ /**
+ * get the handler from a memory chunk holder.
+ *
+ * @param mchunk
+ * specify the memory chunk holder
+ *
+ * @return a handler that could be used to retrieve its memory chunk
+ */
+ abstract public long getChunkHandler(MemChunkHolder<A> mchunk);
+
+ /**
+ * start a application level transaction on this allocator.
+ *
+ */
+ abstract public void beginTransaction();
+
+ /**
+ * end a application level transaction on this allocator.
+ *
+ */
+ abstract public void endTransaction();
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-mnemonic/blob/8e83efe5/core/src/main/java/org/apache/mnemonic/ContainerOverflowException.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/mnemonic/ContainerOverflowException.java b/core/src/main/java/org/apache/mnemonic/ContainerOverflowException.java
new file mode 100644
index 0000000..d6c053a
--- /dev/null
+++ b/core/src/main/java/org/apache/mnemonic/ContainerOverflowException.java
@@ -0,0 +1,20 @@
+package org.apache.mnemonic;
+
+/**
+ * this Exception will be thrown once cache pool has been out of space.
+ *
+ */
+public class ContainerOverflowException extends RuntimeException {
+
+ private static final long serialVersionUID = -8515518456414990004L;
+
+ /**
+ * accept a exception message to describe specific condition.
+ *
+ * @param message
+ * exception message
+ */
+ public ContainerOverflowException(String message) {
+ super(message);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-mnemonic/blob/8e83efe5/core/src/main/java/org/apache/mnemonic/DropEvent.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/mnemonic/DropEvent.java b/core/src/main/java/org/apache/mnemonic/DropEvent.java
new file mode 100644
index 0000000..b3ca93f
--- /dev/null
+++ b/core/src/main/java/org/apache/mnemonic/DropEvent.java
@@ -0,0 +1,24 @@
+package org.apache.mnemonic;
+
+/**
+ * A event listener to monitor and post-process an entry's evacuation.
+ *
+ *
+ */
+public interface DropEvent<KeyT, ValueT> {
+ /**
+ * A call-back actor when an entry has been evicted. a customized drop
+ * action can be implemented on this interface's method e.g. spill this
+ * entry to disk or release associated resources etc.
+ *
+ * @param pool
+ * the pool which an entry has been evicted from
+ *
+ * @param k
+ * the key of an entry that has been evicted
+ *
+ * @param v
+ * the value of an entry that has been evicted
+ */
+ public void drop(CachePool<KeyT, ValueT> pool, KeyT k, ValueT v);
+}
http://git-wip-us.apache.org/repos/asf/incubator-mnemonic/blob/8e83efe5/core/src/main/java/org/apache/mnemonic/Durable.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/mnemonic/Durable.java b/core/src/main/java/org/apache/mnemonic/Durable.java
new file mode 100644
index 0000000..0649dda
--- /dev/null
+++ b/core/src/main/java/org/apache/mnemonic/Durable.java
@@ -0,0 +1,74 @@
+package org.apache.mnemonic;
+
+/**
+ * this interface defines the interactive functionalities with Mnenomic core part.
+ *
+ */
+
+
+public interface Durable {
+
+ /**
+ * this function will be invoked after this non-volatile object is created brandly new
+ *
+ */
+ public void initializeAfterCreate();
+
+ /**
+ * this function will be invoked after this non-volatile object is restored from its allocator
+ *
+ */
+ public void initializeAfterRestore();
+
+
+ /**
+ * this function will be invoked by its factory to setup generic related info to avoid expensive operations from reflection
+ *
+ * @param efproxies
+ * specify a array of factory to proxy the restoring of its generic field objects
+ *
+ * @param gftypes
+ * specify a array of types corresponding to efproxies
+ */
+ public void setupGenericInfo(EntityFactoryProxy[] efproxies, GenericField.GType[] gftypes);
+
+ /**
+ * this function could be called by user code to disable auto-reclaim for this non-volatile object
+ *
+ */
+ public void cancelAutoReclaim();
+
+ /**
+ * this function could be called by user code to register this object for auto-reclaim
+ *
+ */
+ public void registerAutoReclaim();
+
+ /**
+ * this function returns its bound handler for this object
+ *
+ * @return the handler of this object
+ */
+ public long getNonVolatileHandler();
+
+ /**
+ * return the setting for auto-reclaim
+ *
+ * @return the status of the auto-reclaim setting
+ */
+ public boolean autoReclaim();
+
+ /**
+ * manually destroy this object and release its memory resource
+ *
+ */
+ public void destroy() throws RetrieveNonVolatileEntityError;
+
+ /**
+ * return the native field map info for native processing.
+ *
+ * @return the native field map info
+ *
+ */
+ public long[][] getNativeFieldInfo();
+}
http://git-wip-us.apache.org/repos/asf/incubator-mnemonic/blob/8e83efe5/core/src/main/java/org/apache/mnemonic/EntityFactoryProxy.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/mnemonic/EntityFactoryProxy.java b/core/src/main/java/org/apache/mnemonic/EntityFactoryProxy.java
new file mode 100644
index 0000000..89e3ca9
--- /dev/null
+++ b/core/src/main/java/org/apache/mnemonic/EntityFactoryProxy.java
@@ -0,0 +1,35 @@
+package org.apache.mnemonic;
+
+/**
+ * proxy the restoring of generic non-volatile object fields
+ *
+ */
+
+
+public interface EntityFactoryProxy {
+
+ /**
+ * restore a durable object from persistent allocator using a handler of non-volatile object
+ *
+ * @param allocator
+ * specify a persistent allocator instance
+ *
+ * @param factoryproxys
+ * specify an array of factory proxies for its restored non-volatile object
+ *
+ * @param gfields
+ * specify an array of generic types of its generic fields corresponding to factoryproxys
+ *
+ * @param phandler
+ * specify a non-volatile handler to restore
+ *
+ * @param autoreclaim
+ * specify auto-reclaim for this restored non-volatile object
+ *
+ * @return the restored non-volatile object from this factory proxy
+ *
+ */
+ public abstract <A extends CommonPersistAllocator<A>> Durable restore(A allocator,
+ EntityFactoryProxy[] factoryproxys, GenericField.GType[] gfields, long phandler,
+ boolean autoreclaim);
+}
http://git-wip-us.apache.org/repos/asf/incubator-mnemonic/blob/8e83efe5/core/src/main/java/org/apache/mnemonic/EvictFilter.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/mnemonic/EvictFilter.java b/core/src/main/java/org/apache/mnemonic/EvictFilter.java
new file mode 100644
index 0000000..f3a65dd
--- /dev/null
+++ b/core/src/main/java/org/apache/mnemonic/EvictFilter.java
@@ -0,0 +1,24 @@
+package org.apache.mnemonic;
+
+/**
+ * A listener callback to validate its accepted key-value pair for evacuation.
+ *
+ */
+public interface EvictFilter<KeyT, ValueT> {
+ /**
+ * A call-back validator when an entry will be evicted.
+ *
+ * @param pool
+ * the pool which an entry has been evicted from
+ *
+ * @param k
+ * the entry's key
+ *
+ * @param v
+ * the entry's value
+ *
+ * @return <tt>true</tt> if the entry is allowed to be dropped from its
+ * cache pool.
+ */
+ public boolean validate(CachePool<KeyT, ValueT> pool, KeyT k, ValueT v);
+}
http://git-wip-us.apache.org/repos/asf/incubator-mnemonic/blob/8e83efe5/core/src/main/java/org/apache/mnemonic/GenericField.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/mnemonic/GenericField.java b/core/src/main/java/org/apache/mnemonic/GenericField.java
new file mode 100644
index 0000000..0f674a8
--- /dev/null
+++ b/core/src/main/java/org/apache/mnemonic/GenericField.java
@@ -0,0 +1,288 @@
+package org.apache.mnemonic;
+
+/**
+ * this class defines generic field for non-volatile entity
+ *
+ */
+
+import sun.misc.Unsafe;
+
+@SuppressWarnings("restriction")
+public class GenericField<A extends CommonPersistAllocator<A>, E> implements Durable {
+
+ /**
+ * defines the types of generic field
+ *
+ */
+ public enum GType {
+ BOOLEAN, CHARACTER, BYTE, SHORT, INTEGER, LONG, FLOAT, DOUBLE, STRING, DURABLE
+ };
+
+ private Unsafe m_unsafe;
+ private long m_fpos;
+ private GType m_dgftype = null;
+ private Durable m_field = null;
+ private MemBufferHolder<A> m_strfield = null;
+ private A m_allocator;
+ private boolean m_autoreclaim;
+ private EntityFactoryProxy m_defproxy = null;
+ private EntityFactoryProxy[] m_efproxies;
+ private GType[] m_gftypes;
+
+ /**
+ * Constructor: initialize this generic field
+ *
+ * @param defproxy
+ * specify its entity factory proxy
+ *
+ * @param dgftype
+ * specify its type
+ *
+ * @param efproxies
+ * specify an array of containing entity factory proxies
+ *
+ * @param gftypes
+ * specify an array of containing types corresponding to dfproxies
+ *
+ * @param allocator
+ * specify the allocator this field sit on
+ *
+ * @param unsafe
+ * specify the unsafe instance
+ *
+ * @param autoreclaim
+ * specify true if ask for auto-reclaim for this field
+ *
+ * @param fpos
+ * specify the field position
+ *
+ */
+ public GenericField(EntityFactoryProxy defproxy, GType dgftype, EntityFactoryProxy[] efproxies, GType[] gftypes,
+ A allocator, Unsafe unsafe, boolean autoreclaim, Long fpos) {
+ m_unsafe = unsafe;
+ m_fpos = fpos;
+ m_allocator = allocator;
+ m_autoreclaim = autoreclaim;
+ m_efproxies = efproxies;
+ m_gftypes = gftypes;
+ m_defproxy = defproxy;
+ m_dgftype = dgftype;
+ }
+
+ /**
+ * set a value to this field
+ *
+ * @param e
+ * specify a value to set
+ *
+ * @param destroy
+ * specify true if want to destroy the original value
+ */
+ public void set(E e, boolean destroy) {
+ boolean isnull = null == e;
+ switch (m_dgftype) {
+ case BYTE:
+ m_unsafe.putByte(m_fpos, isnull ? (byte)0 : (Byte) e);
+ break;
+ case BOOLEAN:
+ m_unsafe.putByte(m_fpos, isnull ? (byte)0 : ((Boolean) e ? (byte)1 : (byte)0));
+ break;
+ case CHARACTER:
+ m_unsafe.putChar(m_fpos, isnull ? (char)0 : (Character) e);
+ break;
+ case SHORT:
+ m_unsafe.putShort(m_fpos, isnull ? (short)0 : (Short) e);
+ break;
+ case INTEGER:
+ m_unsafe.putInt(m_fpos, isnull ? (int)0 : (Integer) e);
+ break;
+ case LONG:
+ m_unsafe.putLong(m_fpos, isnull ? (long)0 : (Long) e);
+ break;
+ case FLOAT:
+ m_unsafe.putFloat(m_fpos, isnull ? (float)0 : (Float) e);
+ break;
+ case DOUBLE:
+ m_unsafe.putDouble(m_fpos, isnull ? (double)0 : (Double) e);
+ break;
+ case STRING:
+ String str = (String) e;
+ if (destroy && null != get()) {
+ m_strfield.destroy();
+ m_strfield = null;
+ m_unsafe.putAddress(m_fpos, 0L);
+ }
+ if (null == str) {
+ m_unsafe.putAddress(m_fpos, 0L);
+ } else {
+ m_strfield = m_allocator.createBuffer(str.length() * 2, m_autoreclaim);
+ if (null == m_strfield) {
+ throw new OutOfPersistentMemory("Create Persistent String Error!");
+ }
+ m_strfield.get().asCharBuffer().put(str);
+ m_unsafe.putAddress(m_fpos, m_allocator.getBufferHandler(m_strfield));
+ }
+ break;
+ case DURABLE:
+ if (destroy && null != get()) {
+ m_field.destroy();
+ m_field = null;
+ m_unsafe.putAddress(m_fpos, 0L);
+ }
+ m_field = (Durable) e;
+ m_unsafe.putAddress(m_fpos, null == m_field ? 0L : m_field.getNonVolatileHandler());
+ break;
+ }
+
+ }
+
+ /**
+ * get the value of this field
+ *
+ * @return the field value
+ */
+ @SuppressWarnings("unchecked")
+ public E get() {
+ E ret = null;
+ switch (m_dgftype) {
+ case BYTE:
+ ret = (E) Byte.valueOf(m_unsafe.getByte(m_fpos));
+ break;
+ case BOOLEAN:
+ ret = (E) Boolean.valueOf(1 == m_unsafe.getByte(m_fpos));
+ break;
+ case CHARACTER:
+ ret = (E) Character.valueOf(m_unsafe.getChar(m_fpos));
+ break;
+ case SHORT:
+ ret = (E) Short.valueOf(m_unsafe.getShort(m_fpos));
+ break;
+ case INTEGER:
+ ret = (E) Integer.valueOf(m_unsafe.getInt(m_fpos));
+ break;
+ case LONG:
+ ret = (E) Long.valueOf(m_unsafe.getLong(m_fpos));
+ break;
+ case FLOAT:
+ ret = (E) Float.valueOf(m_unsafe.getFloat(m_fpos));
+ break;
+ case DOUBLE:
+ ret = (E) Double.valueOf(m_unsafe.getDouble(m_fpos));
+ break;
+ case STRING:
+ if (null == m_strfield) {
+ long phandler = m_unsafe.getAddress(m_fpos);
+ if (0L != phandler) {
+ m_strfield = m_allocator.retrieveBuffer(phandler, m_autoreclaim);
+ if (null == m_strfield) {
+ throw new RetrieveNonVolatileEntityError("Retrieve String Buffer Failure.");
+ }
+ }
+ }
+ ret = (E) (null == m_strfield ? null : m_strfield.get().asCharBuffer().toString());
+ break;
+ case DURABLE:
+ if (null == m_field) {
+ long phandler = m_unsafe.getAddress(m_fpos);
+ if (0L != phandler) {
+ if (null == m_defproxy) {
+ throw new RetrieveNonVolatileEntityError("Proxy not specified for Non-Volatile Generic entity.");
+ }
+ m_field = m_defproxy.restore(m_allocator, m_efproxies, m_gftypes, phandler, m_autoreclaim);
+ }
+ }
+ ret = (E) m_field;
+ break;
+ }
+ return ret;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void initializeAfterCreate() {
+ throw new UnsupportedOperationException("GenericField.initializeAfterCreate()");
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void initializeAfterRestore() {
+ throw new UnsupportedOperationException("GenericField.initializeAfterRestore()");
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void cancelAutoReclaim() {
+ if (null != m_field) {
+ m_field.cancelAutoReclaim();
+ }
+ if (null != m_strfield) {
+ m_strfield.cancelAutoReclaim();
+ }
+ m_autoreclaim = false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void registerAutoReclaim() {
+ if (null != m_field) {
+ m_field.registerAutoReclaim();
+ }
+ if (null != m_strfield) {
+ m_strfield.registerAutoReclaim();
+ }
+ m_autoreclaim = true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public long getNonVolatileHandler() {
+ throw new UnsupportedOperationException("GenericField.getNonVolatileHandler()");
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean autoReclaim() {
+ return m_autoreclaim;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void destroy() throws RetrieveNonVolatileEntityError {
+ if (null != m_field) {
+ m_field.destroy();
+ }
+ if (null != m_strfield) {
+ m_strfield.destroy();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setupGenericInfo(EntityFactoryProxy[] efproxies, GType[] gftypes) {
+ throw new UnsupportedOperationException("GenericField.setupGenericInfo()");
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public long[][] getNativeFieldInfo() {
+ throw new UnsupportedOperationException("getNativeFieldInfo() on Generic Field.");
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-mnemonic/blob/8e83efe5/core/src/main/java/org/apache/mnemonic/MemBufferHolder.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/mnemonic/MemBufferHolder.java b/core/src/main/java/org/apache/mnemonic/MemBufferHolder.java
new file mode 100644
index 0000000..66ee0bf
--- /dev/null
+++ b/core/src/main/java/org/apache/mnemonic/MemBufferHolder.java
@@ -0,0 +1,56 @@
+package org.apache.mnemonic;
+
+import java.nio.ByteBuffer;
+
+/**
+ * holder for a ByteBuffer instance.
+ *
+ */
+public class MemBufferHolder<A extends CommonAllocator<A>> extends MemHolder<A, ByteBuffer, MemBufferHolder<A>> {
+
+
+ /**
+ * Constructor: initialize with a bytebuffer.
+ *
+ * @param ar
+ * specify an Allocator for this holder
+ *
+ * @param mres
+ * specify a chunk to be holden
+ *
+ */
+ public MemBufferHolder(A ar, ByteBuffer mres) {
+ super(mres, ar);
+ }
+
+ /**
+ * get the size of its held bytebuffer
+ *
+ * @return the size
+ */
+ @Override
+ public long getSize() {
+ return m_mres.capacity();
+ }
+
+ /**
+ * resize its held buffer
+ *
+ * @param size
+ * specify the new size for its held buffer
+ */
+ @Override
+ public MemBufferHolder<A> resize(long size) {
+ return m_allocator.resizeBuffer(this, size);
+ }
+
+ /**
+ * register its held buffer for auto-reclaim
+ *
+ */
+ @Override
+ public void registerAutoReclaim() {
+ m_allocator.registerBufferAutoReclaim(this);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-mnemonic/blob/8e83efe5/core/src/main/java/org/apache/mnemonic/MemBufferHolderCachePool.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/mnemonic/MemBufferHolderCachePool.java b/core/src/main/java/org/apache/mnemonic/MemBufferHolderCachePool.java
new file mode 100644
index 0000000..7634206
--- /dev/null
+++ b/core/src/main/java/org/apache/mnemonic/MemBufferHolderCachePool.java
@@ -0,0 +1,236 @@
+
+package org.apache.mnemonic;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicLong;
+
+/**
+ *
+ * This class inherited from abstract CachePool class that implemented all
+ * inherited abstract methods. it specialized to cache MemBufferHolder objects
+ * that is backed by native memory pool.
+ *
+ */
+public class MemBufferHolderCachePool<KeyT> extends
+ CachePool<KeyT, MemBufferHolder<?>> {
+
+ private static final long serialVersionUID = 684275993324558070L;
+
+ private AtomicLong currentMemory = new AtomicLong(0L);
+
+ private long maxStoreCapacity = 0L;
+
+ /**
+ * Constructs an empty cache pool with specified capacity.
+ *
+ * @param maxCapacity
+ * the capacity of this cache pool
+ *
+ */
+ public MemBufferHolderCachePool(long maxCapacity) {
+ super(512, 0.75f);
+ maxStoreCapacity = maxCapacity;
+ }
+
+ /**
+ * @see CachePool#freeCapacity()
+ */
+ @Override
+ public long freeCapacity() {
+ return maxStoreCapacity - currentMemory.get();
+ }
+
+ /**
+ * @see CachePool#usedCapacity()
+ */
+ @Override
+ public long usedCapacity() {
+ return currentMemory.get();
+ }
+
+ /**
+ * @see Map#remove(Object)
+ */
+ @Override
+ public synchronized MemBufferHolder<?> remove(Object k) {
+ MemBufferHolder<?> ret = super.remove(k);
+ if (null != ret) {
+ currentMemory.getAndAdd(-ret.getSize());
+ }
+ return ret;
+ }
+
+ /**
+ * Associates the specified value with the specified key in this map
+ * (optional operation). If the map previously contained a mapping for the
+ * key, the old value is replaced by the specified value. (A map m is said
+ * to contain a mapping for a key k if and only if m.containsKey(k) would
+ * return true.)
+ *
+ * @param k
+ * key with which the specified value is to be associated
+ *
+ * @param v
+ * MemBufferHolder value to be associated with the specified key
+ *
+ * @return the previous value associated with key, or null if there was no
+ * mapping for key. (A null return can also indicate that the map
+ * previously associated null with key, if the implementation
+ * supports null values.)
+ */
+ @Override
+ public MemBufferHolder<?> put(KeyT k, MemBufferHolder<?> v) {
+ return put(k, v, null, null);
+ }
+
+ /**
+ * @see CachePool#put(Object, Object, DropEvent, EvictFilter)
+ */
+ @Override
+ public MemBufferHolder<?> put(KeyT k, MemBufferHolder<?> v,
+ DropEvent<KeyT, MemBufferHolder<?>> fsop,
+ EvictFilter<KeyT, MemBufferHolder<?>> dfilter) {
+ MemBufferHolder<?> ret = null;
+ long sz = v.getSize();
+ if (containsKey(k)) {
+ sz -= get(k).getSize();
+ }
+ if (sz <= maxStoreCapacity && ensureFreeSpace(sz, fsop, dfilter)) {
+ currentMemory.addAndGet(sz);
+ ret = super.put(k, v);
+ } else {
+ throw new ContainerOverflowException(
+ "Out of capacity of MemBufferHolderCachePool.");
+ }
+ return ret;
+ }
+
+ /**
+ * @see Map#putAll(Map)
+ */
+ @Override
+ public void putAll(
+ Map<? extends KeyT, ? extends MemBufferHolder<?>> m) {
+ putAll(m, null, null);
+ }
+
+ /**
+ * @see CachePool#putAll(Map, DropEvent, EvictFilter)
+ */
+ @Override
+ public void putAll(
+ Map<? extends KeyT, ? extends MemBufferHolder<?>> m,
+ DropEvent<KeyT, MemBufferHolder<?>> fsop,
+ EvictFilter<KeyT, MemBufferHolder<?>> dfilter) {
+
+ long reqsz = 0;
+ for (KeyT k : m.keySet()) {
+ reqsz += m.get(k).getSize();
+ }
+
+ if (reqsz <= maxStoreCapacity && ensureFreeSpace(reqsz, fsop, dfilter)) {
+ currentMemory.addAndGet(reqsz);
+ super.putAll(m);
+ } else {
+ throw new ContainerOverflowException(
+ "Out of capacity of MemBufferHolderCachePool.");
+ }
+ }
+
+ /**
+ * @see CachePool#hotKeySet(int)
+ */
+ @Override
+ public Set<KeyT> hotKeySet(int n) {
+ Set<KeyT> ret = new HashSet<KeyT>();
+ ArrayList<KeyT> keys = new ArrayList<KeyT>(keySet());
+ int endindex = keys.size() > n ? keys.size() - n : 0;
+ for (int i = keys.size(); i > endindex; i--) {
+ ret.add(keys.get(i - 1));
+ }
+ return ret;
+ }
+
+ /**
+ * @see CachePool#ensureFreeSpace(long)
+ */
+ @Override
+ public boolean ensureFreeSpace(long freesz) {
+ return ensureFreeSpace(freesz, null, null);
+ }
+
+ /**
+ * @see CachePool#removeFirstEntry(DropEvent, EvictFilter)
+ */
+ @Override
+ public boolean removeFirstEntry(
+ DropEvent<KeyT, MemBufferHolder<?>> fsop,
+ EvictFilter<KeyT, MemBufferHolder<?>> dfilter) {
+ boolean ret = false;
+ boolean delible = true;
+ for (Map.Entry<KeyT, MemBufferHolder<?>> entry : entrySet()) {
+ if (null != dfilter) {
+ delible = dfilter.validate(this, entry.getKey(),
+ entry.getValue());
+ }
+ if (delible) {
+ KeyT k = entry.getKey();
+ MemBufferHolder<?> v = remove(k);
+ if (null != fsop) {
+ fsop.drop(this, k, v);
+ }
+ ret = true;
+ break;
+ }
+ }
+ return ret;
+ }
+
+ /**
+ * @see CachePool#ensureFreeSpace(long, DropEvent, EvictFilter)
+ */
+ @Override
+ public boolean ensureFreeSpace(long freesz,
+ DropEvent<KeyT, MemBufferHolder<?>> fsop,
+ EvictFilter<KeyT, MemBufferHolder<?>> dfilter) {
+ boolean ret = false;
+
+ if (freesz <= freeCapacity())
+ return true;
+
+ if (freesz > maxStoreCapacity)
+ return false;
+
+ long selectedMemory = 0L;
+ Set<KeyT> selected = new HashSet<KeyT>();
+
+ boolean delible = true;
+ for (Map.Entry<KeyT, MemBufferHolder<?>> entry : entrySet()) {
+ if (null != dfilter) {
+ delible = dfilter.validate(this, entry.getKey(),
+ entry.getValue());
+ }
+ if (delible) {
+ selectedMemory += entry.getValue().getSize();
+ selected.add(entry.getKey());
+ if (freesz <= freeCapacity() + selectedMemory) {
+ ret = true;
+ break;
+ }
+ }
+ }
+ if (ret) {
+ for (KeyT k : selected) {
+ MemBufferHolder<?> mbh = remove(k);
+ if (null != fsop) {
+ fsop.drop(this, k, mbh);
+ }
+ }
+ }
+ return ret;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-mnemonic/blob/8e83efe5/core/src/main/java/org/apache/mnemonic/MemChunkHolder.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/mnemonic/MemChunkHolder.java b/core/src/main/java/org/apache/mnemonic/MemChunkHolder.java
new file mode 100644
index 0000000..28dd639
--- /dev/null
+++ b/core/src/main/java/org/apache/mnemonic/MemChunkHolder.java
@@ -0,0 +1,58 @@
+package org.apache.mnemonic;
+
+/**
+ * holder for a memory chunk.
+ *
+ */
+public class MemChunkHolder<A extends CommonAllocator<A>> extends MemHolder<A, Long, MemChunkHolder<A>> {
+
+ protected long m_size;
+
+ /**
+ * Constructor: initialize with a memory chunk.
+ *
+ * @param ar
+ * specify an Allocator for this holder
+ *
+ * @param mres
+ * specify a chunk to be holden
+ *
+ * @param size
+ * specify the size of this memory chunk
+ */
+ public MemChunkHolder(A ar, Long mres, long size) {
+ super(mres, ar);
+ m_size = size;
+ }
+
+ /**
+ * get the size of its held memory chunk
+ *
+ * @return the size
+ */
+ @Override
+ public long getSize() {
+ return m_size;
+ }
+
+ /**
+ * resize its held chunk
+ *
+ * @param size
+ * specify the new size for its held chunk
+ */
+ @Override
+ public MemChunkHolder<A> resize(long size) {
+ return m_allocator.resizeChunk(this, size);
+ }
+
+ /**
+ * register its held chunk for auto-reclaim
+ *
+ */
+ @Override
+ public void registerAutoReclaim() {
+ m_allocator.registerChunkAutoReclaim(this);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-mnemonic/blob/8e83efe5/core/src/main/java/org/apache/mnemonic/MemClustering.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/mnemonic/MemClustering.java b/core/src/main/java/org/apache/mnemonic/MemClustering.java
new file mode 100644
index 0000000..8494cbb
--- /dev/null
+++ b/core/src/main/java/org/apache/mnemonic/MemClustering.java
@@ -0,0 +1,297 @@
+package org.apache.mnemonic;
+
+import java.util.*;
+
+/**
+ * clustering different kind of memory-like media and combine them as a larger
+ * memory pool for allocation. it will notify user when the underlying memory
+ * storage has been switched or downgraded for the request of allocation
+ *
+ */
+public class MemClustering {
+
+ /**
+ * an interface of event for performance level change.
+ *
+ */
+ public interface PerformanceLevelChange {
+
+ /**
+ * callback if performance level changed
+ *
+ * @param prevlvl
+ * the perf. level before change
+ *
+ * @param tgtlvl
+ * the perf. level after change
+ *
+ */
+ public void changed(PerformanceLevel prevlvl, PerformanceLevel tgtlvl);
+ }
+
+ /**
+ * an interface of event for CommonAllocator change.
+ *
+ */
+ public interface AllocatorChange {
+
+ /**
+ * callback if allocator changed
+ *
+ * @param lvl
+ * the perf. level after changed
+ *
+ * @param prevallocator
+ * the allocator before change
+ *
+ * @param tgtallocator
+ * the allocator after change
+ */
+ public void changed(PerformanceLevel lvl, CommonAllocator<?> prevallocator,
+ CommonAllocator<?> tgtallocator);
+ }
+
+ /**
+ * an interface to assist the creation of memory holder.
+ *
+ * @param <H>
+ * the holder type of memory resource
+ *
+ * @param bma
+ * specify an allocator for this holder
+ *
+ * @param size
+ * specify the size of this memory resource
+ *
+ * @return the holder created
+ */
+ private interface MemCreate<H extends MemHolder<? extends CommonAllocator<?>, ?, ?>> {
+ public H create(CommonAllocator<?> bma, long size);
+ }
+
+
+ private MemCreate<MemChunkHolder<?>> m_memchunkcreate = new MemCreate<MemChunkHolder<?>>() {
+ @Override
+ public MemChunkHolder<?> create(CommonAllocator<?> bma, long size) {
+ return bma.createChunk(size);
+ }
+ };
+
+ private MemCreate<MemBufferHolder<?>> m_membuffercreate = new MemCreate<MemBufferHolder<?>>() {
+ @Override
+ public MemBufferHolder<?> create(CommonAllocator<?> bma, long size) {
+ return bma.createBuffer(size);
+ }
+ };
+
+ /**
+ * performance level categories.
+ *
+ */
+ public static enum PerformanceLevel {
+ FASTEST, FAST, NORMAL, SLOW, SLOWEST
+ }
+
+ /**
+ * configuration for each allocator node.
+ *
+ */
+ public static class NodeConfig<A extends CommonAllocator<A>> {
+ private A m_allocator;
+ private PerformanceLevel m_level;
+
+ /**
+ * Constructor: initialize this instance with specified allocator and perf. level.
+ *
+ * @param a
+ * specify an allocator for this node
+ *
+ * @param l
+ * specify a performance level
+ */
+ public NodeConfig(A a, PerformanceLevel l) {
+ m_allocator = a;
+ m_level = l;
+ }
+
+ /**
+ * retrieve the allocator of this node.
+ *
+ * @return allocator of this node
+ */
+ public A getAllocator() {
+ return m_allocator;
+ }
+
+ /**
+ * retrieve the performance level of this node.
+ *
+ * @return level of this node
+ */
+ public PerformanceLevel getPerformanceLevel() {
+ return m_level;
+ }
+ }
+
+ private PerformanceLevelChange m_bwlvlchange = null;
+ private AllocatorChange m_allocatorChange = null;
+ private PerformanceLevel m_prevbwlevel = null;
+ private CommonAllocator<?> m_prevallocator = null;
+
+
+ private Map<PerformanceLevel, List<CommonAllocator<?>>> m_info;
+
+ /**
+ * Constructor: initialize a memory clustering instance.
+ *
+ * @param ncs
+ * specify a set of node with specified configuration respectively
+ */
+ public MemClustering(NodeConfig<? extends CommonAllocator<?>>[] ncs) {
+ m_info = new EnumMap<PerformanceLevel, List<CommonAllocator<?>>>(
+ PerformanceLevel.class);
+ for (PerformanceLevel lvl : PerformanceLevel.values()) {
+ m_info.put(lvl, new ArrayList<CommonAllocator<?>>());
+ }
+
+ for (NodeConfig<? extends CommonAllocator<?>> nc : ncs) {
+ m_info.get(nc.getPerformanceLevel()).add(nc.getAllocator());
+ }
+
+ }
+
+ /**
+ * set a callback of event for performance level change.
+ *
+ * @param bwlvlchange
+ * specify a callback object for perf. level change
+ */
+ public void setPerformanceLevelChange(PerformanceLevelChange bwlvlchange) {
+ m_bwlvlchange = bwlvlchange;
+ }
+
+ /**
+ * set a callback of event for allocator change.
+ *
+ * @param allocatorChange
+ * specify a callback object for allocator change
+ */
+ public <A extends CommonAllocator<A>> void setAllocatorChange(AllocatorChange allocatorChange) {
+ m_allocatorChange = allocatorChange;
+ }
+
+ /**
+ * a factory to create memory resource.
+ *
+ * @param <H> the type of holder
+ *
+ * @param creator
+ * specify a creator to delegate concrete holder creation
+ *
+ * @param startlevel
+ * specify a perf. level that is the start level for memory resource
+ * allocation
+ *
+ * @param size
+ * specify a size to request memory resource
+ *
+ * @return a new created holder held an allocated memory resource
+ */
+ protected <H extends MemHolder<? extends CommonAllocator<?>, ?, ?>> H
+ create(MemCreate<H> creator, PerformanceLevel startlevel, long size) {
+ H ret = null;
+ boolean eligible = false;
+ for (PerformanceLevel lvl : m_info.keySet()) {
+ if (!eligible && startlevel == lvl) {
+ eligible = true;
+ }
+ if (eligible) {
+ int distance = 0;
+ List<CommonAllocator<?>> bmas = m_info.get(lvl);
+ for (CommonAllocator<?> bma : bmas) {
+ ret = creator.create(bma, size);
+ if (null == ret) {
+ distance++;
+ } else {
+ if (null != m_bwlvlchange && m_prevbwlevel != lvl) {
+ m_bwlvlchange.changed(m_prevbwlevel, lvl);
+ m_prevbwlevel = lvl;
+ }
+ if (null != m_allocatorChange && m_prevallocator != bma) {
+ m_allocatorChange.changed(lvl, m_prevallocator, bma);
+ m_prevallocator = bma;
+ }
+ break;
+ }
+ }
+ Collections.rotate(bmas, distance);
+ }
+ if (null != ret) {
+ break;
+ }
+ }
+ return ret;
+ }
+
+ /**
+ * create a chunk from this clustering.
+ *
+ * @param size
+ * specify the size of memory chunk
+ *
+ * @return a holder with a created chunk
+ *
+ */
+ //@Override
+ public MemChunkHolder<?> createChunk(long size) {
+ return createChunk(PerformanceLevel.FASTEST, size);
+ }
+
+ /**
+ * create a chunk from this clustering
+ *
+ * @param startlevel
+ * specify the perf. level from which to search qualified
+ * node.
+ *
+ * @param size
+ * specify the size of memory chunk
+ *
+ * @return a holder with a created chunk
+ */
+ public MemChunkHolder<?> createChunk(PerformanceLevel startlevel, long size) {
+ return create(m_memchunkcreate, startlevel, size);
+ }
+
+ /**
+ * create a buffer from this clustering.
+ *
+ * @param size
+ * specify the size of memory buffer
+ *
+ * @return a holder with a created buffer
+ *
+ */
+ //@Override
+ public MemBufferHolder<?> createBuffer(long size) {
+ return createBuffer(PerformanceLevel.FASTEST, size);
+ }
+
+ /**
+ * create a buffer from this clustering
+ *
+ * @param startlevel
+ * specify the perf. level from which to search qualified
+ * node.
+ *
+ * @param size
+ * specify the size of memory buffer
+ *
+ * @return a holder with a created buffer
+ */
+ public MemBufferHolder<?> createBuffer(PerformanceLevel startlevel,
+ long size) {
+ return create(m_membuffercreate, startlevel, size);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-mnemonic/blob/8e83efe5/core/src/main/java/org/apache/mnemonic/MemFile.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/mnemonic/MemFile.java b/core/src/main/java/org/apache/mnemonic/MemFile.java
new file mode 100644
index 0000000..08fb0d7
--- /dev/null
+++ b/core/src/main/java/org/apache/mnemonic/MemFile.java
@@ -0,0 +1,51 @@
+
+package org.apache.mnemonic;
+
+import java.io.File;
+
+/**
+ * a memory file that manages its data on native memory storage. Note: this
+ * class depends on PMFS, we suggest that NVM library to support this feature in
+ * native layer. In addition, the permission of /mnt/pmfs will be set properly.
+ *
+ *
+ */
+public class MemFile extends File {
+
+ private static final long serialVersionUID = 6579668848729471173L;
+ private String uri, id;
+
+ /**
+ * initialize the memory file.
+ *
+ * @param uri
+ * specify the location of memory file
+ *
+ * @param id
+ * specify the id of memory file
+ */
+ public MemFile(String uri, String id) {
+ super(uri, id);
+ this.uri = uri;
+ this.id = id;
+ }
+
+ /**
+ * retrieve the uri of this memory file.
+ *
+ * @return the uri of memory file
+ */
+ public String getUri() {
+ return this.uri;
+ }
+
+ /**
+ * retrieve the id of this memory file.
+ *
+ * @return the id of memory file
+ */
+ public String getId() {
+ return this.id;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-mnemonic/blob/8e83efe5/core/src/main/java/org/apache/mnemonic/MemHolder.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/mnemonic/MemHolder.java b/core/src/main/java/org/apache/mnemonic/MemHolder.java
new file mode 100644
index 0000000..b52e50a
--- /dev/null
+++ b/core/src/main/java/org/apache/mnemonic/MemHolder.java
@@ -0,0 +1,58 @@
+package org.apache.mnemonic;
+
+import org.flowcomputing.commons.resgc.*;
+
+/**
+ * hold a memory kind of resource.
+ *
+ */
+public abstract class MemHolder<A extends CommonAllocator<A>, T, H extends MemHolder<A, T, H>> extends ResHolder<T, H> {
+
+ protected A m_allocator;
+
+ /**
+ * Constructor: initialize with resource.
+ *
+ * @param mres
+ * specify a resource to be holden
+ *
+ * @param ar
+ * specify an Allocator for this holder
+ *
+ */
+ public MemHolder(T mres, A ar) {
+ super(mres);
+ m_allocator = ar;
+ }
+
+ /**
+ * get its allocator
+ *
+ * @return the allocator
+ */
+ public A getAllocator() {
+ return m_allocator;
+ }
+
+ /**
+ * resize its held resource
+ *
+ * @param size
+ * specify the new size for its held resource
+ */
+ abstract public MemHolder<A, T, H> resize(long size);
+
+ /**
+ * get the size of its held memory resource.
+ *
+ * @return the size
+ */
+ abstract public long getSize();
+
+ /**
+ * register its held resource for auto-reclaim
+ *
+ */
+ abstract public void registerAutoReclaim();
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-mnemonic/blob/8e83efe5/core/src/main/java/org/apache/mnemonic/MemoryNonVolatileEntity.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/mnemonic/MemoryNonVolatileEntity.java b/core/src/main/java/org/apache/mnemonic/MemoryNonVolatileEntity.java
new file mode 100644
index 0000000..87010d5
--- /dev/null
+++ b/core/src/main/java/org/apache/mnemonic/MemoryNonVolatileEntity.java
@@ -0,0 +1,19 @@
+package org.apache.mnemonic;
+
+/**
+ *
+ *
+ */
+
+
+public interface MemoryNonVolatileEntity<ALLOC_PMem3C93D24F59 extends CommonPersistAllocator<ALLOC_PMem3C93D24F59>> {
+
+ public void initializeNonVolatileEntity(ALLOC_PMem3C93D24F59 allocator, EntityFactoryProxy[] efproxys, GenericField.GType[] gfields, boolean autoreclaim);
+
+ public void createNonVolatileEntity(ALLOC_PMem3C93D24F59 allocator, EntityFactoryProxy[] efproxys, GenericField.GType[] gfields, boolean autoreclaim)
+ throws OutOfPersistentMemory;
+
+ public void restoreNonVolatileEntity(ALLOC_PMem3C93D24F59 allocator, EntityFactoryProxy[] efproxys, GenericField.GType[] gfields, long phandler, boolean autoreclaim)
+ throws RetrieveNonVolatileEntityError;
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-mnemonic/blob/8e83efe5/core/src/main/java/org/apache/mnemonic/NonVolatileEntity.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/mnemonic/NonVolatileEntity.java b/core/src/main/java/org/apache/mnemonic/NonVolatileEntity.java
new file mode 100644
index 0000000..6c2aabb
--- /dev/null
+++ b/core/src/main/java/org/apache/mnemonic/NonVolatileEntity.java
@@ -0,0 +1,13 @@
+package org.apache.mnemonic;
+
+/**
+ * this class defines a annotation for non-volatile entity
+ *
+ */
+
+import java.lang.annotation.*;
+
+@Target(ElementType.TYPE) @Retention(RetentionPolicy.CLASS)
+public @interface NonVolatileEntity {
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-mnemonic/blob/8e83efe5/core/src/main/java/org/apache/mnemonic/NonVolatileEntityProcessor.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/mnemonic/NonVolatileEntityProcessor.java b/core/src/main/java/org/apache/mnemonic/NonVolatileEntityProcessor.java
new file mode 100644
index 0000000..b9e83c6
--- /dev/null
+++ b/core/src/main/java/org/apache/mnemonic/NonVolatileEntityProcessor.java
@@ -0,0 +1,134 @@
+package org.apache.mnemonic;
+
+/**
+ * a non-volatile annotation processor
+ *
+ */
+
+import java.io.IOException;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import javax.annotation.processing.*;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.util.ElementFilter;
+import javax.lang.model.util.Elements;
+import javax.lang.model.util.Types;
+
+import javax.tools.Diagnostic;
+
+import com.squareup.javapoet.MethodSpec;
+
+public class NonVolatileEntityProcessor extends AbstractProcessor {
+ private Types typeUtils;
+ private Elements elementUtils;
+ private Filer filer;
+ private Messager messager;
+ // private Map<String, FactoryGroupedClasses> factoryClasses = new
+ // LinkedHashMap<String, FactoryGroupedClasses>();
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public synchronized void init(ProcessingEnvironment processingEnv) {
+ super.init(processingEnv);
+ typeUtils = processingEnv.getTypeUtils();
+ elementUtils = processingEnv.getElementUtils();
+ filer = processingEnv.getFiler();
+ messager = processingEnv.getMessager();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Set<String> getSupportedAnnotationTypes() {
+ Set<String> annotataions = new LinkedHashSet<String>();
+ annotataions.add(NonVolatileEntity.class.getCanonicalName());
+ return annotataions;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public SourceVersion getSupportedSourceVersion() {
+ return SourceVersion.latestSupported();
+ }
+
+ /**
+ * triggered if an error issued during processing
+ *
+ * @param e
+ * the element in question
+ *
+ * @param msg
+ * the message issued
+ */
+ public void error(Element e, String msg) {
+ messager.printMessage(Diagnostic.Kind.ERROR, msg, e);
+ }
+
+ /**
+ * triggered if a note issued during processing
+ *
+ * @param e
+ * the element in question
+ *
+ * @param msg
+ * the message issued
+ */
+ public void note(Element e, String msg) {
+ messager.printMessage(Diagnostic.Kind.NOTE, msg, e);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+
+ try {
+
+ for (Element annotatedElement : roundEnv.getElementsAnnotatedWith(NonVolatileEntity.class)) {
+
+ String outputstr = String.format("++++++++++%s+++++++++++", annotatedElement.getSimpleName());
+ note(annotatedElement, outputstr);
+ // System.err.println(outputstr);
+
+ if (annotatedElement.getKind() != ElementKind.CLASS) {
+ throw new AnnotationProcessingException(
+ annotatedElement, "Only classes can be annotated with @%s",
+ NonVolatileEntity.class.getSimpleName());
+ }
+
+ // We can cast it, because we know that it of ElementKind.CLASS
+ TypeElement typeelem = (TypeElement) annotatedElement;
+
+ AnnotatedNonVolatileEntityClass annotatedClass =
+ new AnnotatedNonVolatileEntityClass(typeelem, typeUtils, elementUtils, messager);
+
+ annotatedClass.prepareProcessing();
+
+ annotatedClass.generateCode(filer);
+
+ }
+
+ } catch (AnnotationProcessingException e) {
+ error(e.getElement(), e.getMessage());
+ } catch (IOException e) {
+ error(null, e.getMessage());
+ }
+
+ return true;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-mnemonic/blob/8e83efe5/core/src/main/java/org/apache/mnemonic/NonVolatileGetter.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/mnemonic/NonVolatileGetter.java b/core/src/main/java/org/apache/mnemonic/NonVolatileGetter.java
new file mode 100644
index 0000000..be88be8
--- /dev/null
+++ b/core/src/main/java/org/apache/mnemonic/NonVolatileGetter.java
@@ -0,0 +1,18 @@
+package org.apache.mnemonic;
+
+/**
+ * this class defines an annotation for getter methods of non-volatile entity
+ *
+ */
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target(ElementType.METHOD) @Retention(RetentionPolicy.CLASS)
+public @interface NonVolatileGetter {
+ String EntityFactoryProxies() default "null";
+ String GenericFieldTypes() default "null";
+ long Id() default -1L;
+}
http://git-wip-us.apache.org/repos/asf/incubator-mnemonic/blob/8e83efe5/core/src/main/java/org/apache/mnemonic/NonVolatileSetter.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/mnemonic/NonVolatileSetter.java b/core/src/main/java/org/apache/mnemonic/NonVolatileSetter.java
new file mode 100644
index 0000000..11dfba2
--- /dev/null
+++ b/core/src/main/java/org/apache/mnemonic/NonVolatileSetter.java
@@ -0,0 +1,16 @@
+package org.apache.mnemonic;
+
+/**
+ * this class defines an annotation for setter methods of non-volatile entity
+ *
+ */
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target(ElementType.METHOD) @Retention(RetentionPolicy.CLASS)
+public @interface NonVolatileSetter {
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-mnemonic/blob/8e83efe5/core/src/main/java/org/apache/mnemonic/OutOfPersistentMemory.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/mnemonic/OutOfPersistentMemory.java b/core/src/main/java/org/apache/mnemonic/OutOfPersistentMemory.java
new file mode 100644
index 0000000..bb1d042
--- /dev/null
+++ b/core/src/main/java/org/apache/mnemonic/OutOfPersistentMemory.java
@@ -0,0 +1,15 @@
+package org.apache.mnemonic;
+
+/**
+ * this is an exception that should be throw once out of persistent memory
+ *
+ */
+
+public class OutOfPersistentMemory extends RuntimeException {
+
+ private static final long serialVersionUID = -6315943783592441148L;
+
+ public OutOfPersistentMemory(String s) {
+ super(s);
+ }
+}