/** * Resize an existing block to new capacity by slicing the <code>Pointer</code> pointed to by * existing pointer. The new <code>Pointer</code> is a slice present before the existing. * * @param existing points to existing Pointer(referring existing block). * @param capacity to be resized to. * @return Pointer to resized block. */ private Pointer slice(Pointer existing, int capacity) { if ((existing.getEnd() - existing.getStart()) == capacity + 1 && existing.isFree()) { return existing; } Pointer fresh = new Pointer(); fresh.setBlockNumber(existing.getBlockNumber()); fresh.setStart(existing.getStart()); fresh.setEnd(fresh.getStart() + capacity); fresh.setFree(true); fresh.setPrev(existing.getPrev()); existing.setPrev(fresh); fresh.setNext(existing); existing.setStart(existing.getStart() + (capacity + 1)); return fresh; }
/* * (non-Javadoc) * * @see com.prashant.memory.MemoryBuffer#store(byte[], int) */ public synchronized Pointer store(byte[] payload, int capacity) throws DMBufferOverFlowException { // First good match is page that has capacity equal or greater than // payload. Pointer goodOne = firstMatch(capacity); if (goodOne == null) { RuntimeException e = new NullPointerException(); // logger.error("Did not find a suitable buffer"); throw new DMBufferOverFlowException("did not find a suitable buffer", e.getCause()); } Pointer fresh = slice(goodOne, capacity); fresh.setFree(false); used.addAndGet(payload.length); ByteBuffer buf = buffer.slice(); buf.position(fresh.getStart()); try { buf.put(payload); } catch (BufferOverflowException e) { goodOne.setStart(fresh.getStart()); goodOne.setEnd(buffer.limit()); // return null; //Uncomment incase we want to ignore this exception. throw new DMBufferOverFlowException( "An attempt to store more than the configured capacity", e.getCause()); } pointers.add(fresh); return fresh; }
/** * It is synchronized as it does merging of adjacent blocks. An easiest way to somewhat address * fragmentation problem. * * @param pointer2free */ private void freeAndMerge(Pointer pointer2free) { synchronized (pointers) { pointers.remove(pointer2free); // merge adjacent blocks if (null != pointer2free.getPrev() && pointer2free.getPrev().isFree()) { // Merge previous pointers.remove(pointer2free.getPrev()); pointer2free.setStart(pointer2free.getPrev().getStart()); pointer2free.setPrev(pointer2free.getPrev().getPrev()); // Recursive call freeAndMerge(pointer2free); } if (null != pointer2free.getNext() && pointer2free.getNext().isFree()) { // Merge Next pointers.remove(pointer2free.getNext()); pointer2free.setEnd(pointer2free.getNext().getEnd()); pointer2free.setNext(pointer2free.getNext().getNext()); // Recursive call freeAndMerge(pointer2free); } if (!pointer2free.isFree()) { pointer2free.setFree(true); pointer2free.setClazz(null); pointers.add(pointer2free); } } }
private Pointer createAndAddFirstPointer() { Pointer first = new Pointer(); first.setBlockNumber(0); first.setStart(0); first.setFree(true); first.setEnd(buffer.capacity() - 1); first.setNext(null); first.setPrev(null); pointers.add(first); return first; }