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