/** * This file is part of ObjectFabric (http://objectfabric.org). * * ObjectFabric is licensed under the Apache License, Version 2.0, the terms * of which may be found at http://www.apache.org/licenses/LICENSE-2.0.html. * * Copyright ObjectFabric Inc. * * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ package org.objectfabric; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.nio.ByteBuffer; import java.nio.ByteOrder; @SuppressWarnings("serial") class JVMBuff extends Buff { // TODO x86 specific version with Unsafe? private final ByteBuffer _buffer; JVMBuff(int capacity, boolean recycle) { super(recycle); _buffer = ByteBuffer.allocateDirect(capacity); _buffer.order(ByteOrder.LITTLE_ENDIAN); } private JVMBuff(Buff parent, ByteBuffer buffer) { super(parent); _buffer = buffer; _buffer.order(ByteOrder.LITTLE_ENDIAN); } static JVMBuff getWithPosition(int position) { JVMBuff buff = (JVMBuff) Buff.getOrCreate(); buff.position(position); if (Debug.RANDOMIZE_TRANSFER_LENGTHS) { int limit = Math.min(buff.remaining(), 200); int rand = Platform.get().randomInt(limit - 1) + 1; buff.limit(position + rand); } return buff; } @Override Buff duplicateInternals(Buff parent) { JVMBuff buff = new JVMBuff(parent, _buffer.duplicate()); if (Debug.ENABLED) check(false); return buff; } final ByteBuffer getByteBuffer() { return _buffer; } @Override final void destroy() { // TODO something better try { Field field = _buffer.getClass().getDeclaredField("cleaner"); field.setAccessible(true); Object cleaner = field.get(_buffer); Method method = cleaner.getClass().getMethod("clean"); method.setAccessible(true); method.invoke(cleaner); } catch (Exception e) { Log.write(e); } } // @Override final int capacity() { if (Debug.ENABLED) check(false); int value = _buffer.capacity(); if (Debug.ENABLED) check(false); return value; } @Override final int position() { if (Debug.ENABLED) check(false); int value = _buffer.position(); if (Debug.ENABLED) check(false); return value; } @Override final void position(int value) { if (Debug.ENABLED) check(false); _buffer.position(value); if (Debug.ENABLED) check(false); } @Override final int limit() { if (Debug.ENABLED) check(false); int value = _buffer.limit(); if (Debug.ENABLED) check(false); return value; } @Override final void limit(int value) { if (Debug.ENABLED) check(false); _buffer.limit(value); if (Debug.ENABLED) check(false); } @Override void mark() { if (Debug.ENABLED) check(false); _buffer.mark(); if (Debug.ENABLED) check(false); } @Override final void reset() { if (Debug.ENABLED) check(false); _buffer.reset(); if (Debug.ENABLED) check(false); } // @Override final byte getByte() { if (Debug.ENABLED) check(false); return _buffer.get(); } @Override final void putByte(byte value) { if (Debug.ENABLED) check(true); _buffer.put(value); } @Override final short getShort() { if (Debug.ENABLED) check(false); return _buffer.getShort(); } @Override final void putShort(short value) { if (Debug.ENABLED) check(true); _buffer.putShort(value); } @Override final char getChar() { if (Debug.ENABLED) check(false); return _buffer.getChar(); } @Override final void putChar(char value) { if (Debug.ENABLED) check(true); _buffer.putChar(value); } @Override final int getInt() { if (Debug.ENABLED) check(false); return _buffer.getInt(); } @Override final void putInt(int value) { if (Debug.ENABLED) check(true); _buffer.putInt(value); } @Override final long getLong() { if (Debug.ENABLED) check(false); return _buffer.getLong(); } @Override final void putLong(long value) { if (Debug.ENABLED) check(true); _buffer.putLong(value); } // @Override final void getImmutably(byte[] bytes, int offset, int length) { if (Debug.ENABLED) check(false); _buffer.duplicate().get(bytes, offset, length); } @Override final void putImmutably(byte[] bytes, int offset, int length) { if (Debug.ENABLED) check(true); _buffer.duplicate().put(bytes, offset, length); } @Override final void putImmutably(Buff source) { _buffer.put(((JVMBuff) source)._buffer.duplicate()); } @Override final void putLeftover(Buff source) { int remaining = source.remaining(); position(position() - remaining); _buffer.put(((JVMBuff) source)._buffer); position(position() - remaining); } // Debug // For Chronon recording static final class TestBuff extends JVMBuff { int _position, _limit, _mark; TestBuff(int capacity, boolean recycle) { super(capacity, recycle); } @Override void check(boolean write) { super.check(write); _position = getByteBuffer().position(); _limit = getByteBuffer().limit(); } @Override void mark() { super.mark(); _mark = getByteBuffer().position(); } } }