1 // Copyright (c) 2011-present, Facebook, Inc. All rights reserved. 2 // This source code is licensed under both the GPLv2 (found in the 3 // COPYING file in the root directory) and Apache 2.0 License 4 // (found in the LICENSE.Apache file in the root directory). 5 6 package org.rocksdb; 7 8 import java.nio.ByteBuffer; 9 10 /** 11 * Base class for slices which will receive direct 12 * ByteBuffer based access to the underlying data. 13 * 14 * ByteBuffer backed slices typically perform better with 15 * larger keys and values. When using smaller keys and 16 * values consider using @see org.rocksdb.Slice 17 */ 18 public class DirectSlice extends AbstractSlice<ByteBuffer> { 19 public final static DirectSlice NONE = new DirectSlice(); 20 21 /** 22 * Indicates whether we have to free the memory pointed to by the Slice 23 */ 24 private final boolean internalBuffer; 25 private volatile boolean cleared = false; 26 private volatile long internalBufferOffset = 0; 27 28 /** 29 * Called from JNI to construct a new Java DirectSlice 30 * without an underlying C++ object set 31 * at creation time. 32 * 33 * Note: You should be aware that it is intentionally marked as 34 * package-private. This is so that developers cannot construct their own 35 * default DirectSlice objects (at present). As developers cannot construct 36 * their own DirectSlice objects through this, they are not creating 37 * underlying C++ DirectSlice objects, and so there is nothing to free 38 * (dispose) from Java. 39 */ DirectSlice()40 DirectSlice() { 41 super(); 42 this.internalBuffer = false; 43 } 44 45 /** 46 * Constructs a slice 47 * where the data is taken from 48 * a String. 49 * 50 * @param str The string 51 */ DirectSlice(final String str)52 public DirectSlice(final String str) { 53 super(createNewSliceFromString(str)); 54 this.internalBuffer = true; 55 } 56 57 /** 58 * Constructs a slice where the data is 59 * read from the provided 60 * ByteBuffer up to a certain length 61 * 62 * @param data The buffer containing the data 63 * @param length The length of the data to use for the slice 64 */ DirectSlice(final ByteBuffer data, final int length)65 public DirectSlice(final ByteBuffer data, final int length) { 66 super(createNewDirectSlice0(ensureDirect(data), length)); 67 this.internalBuffer = false; 68 } 69 70 /** 71 * Constructs a slice where the data is 72 * read from the provided 73 * ByteBuffer 74 * 75 * @param data The bugger containing the data 76 */ DirectSlice(final ByteBuffer data)77 public DirectSlice(final ByteBuffer data) { 78 super(createNewDirectSlice1(ensureDirect(data))); 79 this.internalBuffer = false; 80 } 81 ensureDirect(final ByteBuffer data)82 private static ByteBuffer ensureDirect(final ByteBuffer data) { 83 if(!data.isDirect()) { 84 throw new IllegalArgumentException("The ByteBuffer must be direct"); 85 } 86 return data; 87 } 88 89 /** 90 * Retrieves the byte at a specific offset 91 * from the underlying data 92 * 93 * @param offset The (zero-based) offset of the byte to retrieve 94 * 95 * @return the requested byte 96 */ get(final int offset)97 public byte get(final int offset) { 98 return get0(getNativeHandle(), offset); 99 } 100 101 @Override clear()102 public void clear() { 103 clear0(getNativeHandle(), !cleared && internalBuffer, internalBufferOffset); 104 cleared = true; 105 } 106 107 @Override removePrefix(final int n)108 public void removePrefix(final int n) { 109 removePrefix0(getNativeHandle(), n); 110 this.internalBufferOffset += n; 111 } 112 113 @Override disposeInternal()114 protected void disposeInternal() { 115 final long nativeHandle = getNativeHandle(); 116 if(!cleared && internalBuffer) { 117 disposeInternalBuf(nativeHandle, internalBufferOffset); 118 } 119 disposeInternal(nativeHandle); 120 } 121 createNewDirectSlice0(final ByteBuffer data, final int length)122 private native static long createNewDirectSlice0(final ByteBuffer data, 123 final int length); createNewDirectSlice1(final ByteBuffer data)124 private native static long createNewDirectSlice1(final ByteBuffer data); data0(long handle)125 @Override protected final native ByteBuffer data0(long handle); get0(long handle, int offset)126 private native byte get0(long handle, int offset); clear0(long handle, boolean internalBuffer, long internalBufferOffset)127 private native void clear0(long handle, boolean internalBuffer, 128 long internalBufferOffset); removePrefix0(long handle, int length)129 private native void removePrefix0(long handle, int length); disposeInternalBuf(final long handle, long internalBufferOffset)130 private native void disposeInternalBuf(final long handle, 131 long internalBufferOffset); 132 } 133