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 /** 9 * Slices are used by RocksDB to provide 10 * efficient access to keys and values. 11 * 12 * This class is package private, implementers 13 * should extend either of the public abstract classes: 14 * @see org.rocksdb.Slice 15 * @see org.rocksdb.DirectSlice 16 * 17 * Regards the lifecycle of Java Slices in RocksDB: 18 * At present when you configure a Comparator from Java, it creates an 19 * instance of a C++ BaseComparatorJniCallback subclass and 20 * passes that to RocksDB as the comparator. That subclass of 21 * BaseComparatorJniCallback creates the Java 22 * @see org.rocksdb.AbstractSlice subclass Objects. When you dispose 23 * the Java @see org.rocksdb.AbstractComparator subclass, it disposes the 24 * C++ BaseComparatorJniCallback subclass, which in turn destroys the 25 * Java @see org.rocksdb.AbstractSlice subclass Objects. 26 */ 27 public abstract class AbstractSlice<T> extends RocksMutableObject { 28 AbstractSlice()29 protected AbstractSlice() { 30 super(); 31 } 32 AbstractSlice(final long nativeHandle)33 protected AbstractSlice(final long nativeHandle) { 34 super(nativeHandle); 35 } 36 37 /** 38 * Returns the data of the slice. 39 * 40 * @return The slice data. Note, the type of access is 41 * determined by the subclass 42 * @see org.rocksdb.AbstractSlice#data0(long) 43 */ data()44 public T data() { 45 return data0(getNativeHandle()); 46 } 47 48 /** 49 * Access to the data is provided by the 50 * subtype as it needs to handle the 51 * generic typing. 52 * 53 * @param handle The address of the underlying 54 * native object. 55 * 56 * @return Java typed access to the data. 57 */ data0(long handle)58 protected abstract T data0(long handle); 59 60 /** 61 * Drops the specified {@code n} 62 * number of bytes from the start 63 * of the backing slice 64 * 65 * @param n The number of bytes to drop 66 */ removePrefix(final int n)67 public abstract void removePrefix(final int n); 68 69 /** 70 * Clears the backing slice 71 */ clear()72 public abstract void clear(); 73 74 /** 75 * Return the length (in bytes) of the data. 76 * 77 * @return The length in bytes. 78 */ size()79 public int size() { 80 return size0(getNativeHandle()); 81 } 82 83 /** 84 * Return true if the length of the 85 * data is zero. 86 * 87 * @return true if there is no data, false otherwise. 88 */ empty()89 public boolean empty() { 90 return empty0(getNativeHandle()); 91 } 92 93 /** 94 * Creates a string representation of the data 95 * 96 * @param hex When true, the representation 97 * will be encoded in hexadecimal. 98 * 99 * @return The string representation of the data. 100 */ toString(final boolean hex)101 public String toString(final boolean hex) { 102 return toString0(getNativeHandle(), hex); 103 } 104 105 @Override toString()106 public String toString() { 107 return toString(false); 108 } 109 110 /** 111 * Three-way key comparison 112 * 113 * @param other A slice to compare against 114 * 115 * @return Should return either: 116 * 1) < 0 if this < other 117 * 2) == 0 if this == other 118 * 3) > 0 if this > other 119 */ compare(final AbstractSlice<?> other)120 public int compare(final AbstractSlice<?> other) { 121 assert (other != null); 122 if(!isOwningHandle()) { 123 return other.isOwningHandle() ? -1 : 0; 124 } else { 125 if(!other.isOwningHandle()) { 126 return 1; 127 } else { 128 return compare0(getNativeHandle(), other.getNativeHandle()); 129 } 130 } 131 } 132 133 @Override hashCode()134 public int hashCode() { 135 return toString().hashCode(); 136 } 137 138 /** 139 * If other is a slice object, then 140 * we defer to {@link #compare(AbstractSlice) compare} 141 * to check equality, otherwise we return false. 142 * 143 * @param other Object to test for equality 144 * 145 * @return true when {@code this.compare(other) == 0}, 146 * false otherwise. 147 */ 148 @Override equals(final Object other)149 public boolean equals(final Object other) { 150 if (other != null && other instanceof AbstractSlice) { 151 return compare((AbstractSlice<?>)other) == 0; 152 } else { 153 return false; 154 } 155 } 156 157 /** 158 * Determines whether this slice starts with 159 * another slice 160 * 161 * @param prefix Another slice which may of may not 162 * be a prefix of this slice. 163 * 164 * @return true when this slice starts with the 165 * {@code prefix} slice 166 */ startsWith(final AbstractSlice<?> prefix)167 public boolean startsWith(final AbstractSlice<?> prefix) { 168 if (prefix != null) { 169 return startsWith0(getNativeHandle(), prefix.getNativeHandle()); 170 } else { 171 return false; 172 } 173 } 174 createNewSliceFromString(final String str)175 protected native static long createNewSliceFromString(final String str); size0(long handle)176 private native int size0(long handle); empty0(long handle)177 private native boolean empty0(long handle); toString0(long handle, boolean hex)178 private native String toString0(long handle, boolean hex); compare0(long handle, long otherHandle)179 private native int compare0(long handle, long otherHandle); startsWith0(long handle, long otherHandle)180 private native boolean startsWith0(long handle, long otherHandle); 181 182 /** 183 * Deletes underlying C++ slice pointer. 184 * Note that this function should be called only after all 185 * RocksDB instances referencing the slice are closed. 186 * Otherwise an undefined behavior will occur. 187 */ 188 @Override disposeInternal(final long handle)189 protected final native void disposeInternal(final long handle); 190 191 } 192