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.util.Arrays; 9 import java.util.Objects; 10 11 /** 12 * ColumnFamilyHandle class to hold handles to underlying rocksdb 13 * ColumnFamily Pointers. 14 */ 15 public class ColumnFamilyHandle extends RocksObject { 16 /** 17 * Constructs column family Java object, which operates on underlying native object. 18 * 19 * @param rocksDB db instance associated with this column family 20 * @param nativeHandle native handle to underlying native ColumnFamily object 21 */ ColumnFamilyHandle(final RocksDB rocksDB, final long nativeHandle)22 ColumnFamilyHandle(final RocksDB rocksDB, 23 final long nativeHandle) { 24 super(nativeHandle); 25 // rocksDB must point to a valid RocksDB instance; 26 assert(rocksDB != null); 27 // ColumnFamilyHandle must hold a reference to the related RocksDB instance 28 // to guarantee that while a GC cycle starts ColumnFamilyHandle instances 29 // are freed prior to RocksDB instances. 30 this.rocksDB_ = rocksDB; 31 } 32 33 /** 34 * Constructor called only from JNI. 35 * 36 * NOTE: we are producing an additional Java Object here to represent the underlying native C++ 37 * ColumnFamilyHandle object. The underlying object is not owned by ourselves. The Java API user 38 * likely already had a ColumnFamilyHandle Java object which owns the underlying C++ object, as 39 * they will have been presented it when they opened the database or added a Column Family. 40 * 41 * 42 * TODO(AR) - Potentially a better design would be to cache the active Java Column Family Objects 43 * in RocksDB, and return the same Java Object instead of instantiating a new one here. This could 44 * also help us to improve the Java API semantics for Java users. See for example 45 * https://github.com/facebook/rocksdb/issues/2687. 46 * 47 * @param nativeHandle native handle to the column family. 48 */ ColumnFamilyHandle(final long nativeHandle)49 ColumnFamilyHandle(final long nativeHandle) { 50 super(nativeHandle); 51 rocksDB_ = null; 52 disOwnNativeHandle(); 53 } 54 55 /** 56 * Gets the name of the Column Family. 57 * 58 * @return The name of the Column Family. 59 * 60 * @throws RocksDBException if an error occurs whilst retrieving the name. 61 */ getName()62 public byte[] getName() throws RocksDBException { 63 assert(isOwningHandle() || isDefaultColumnFamily()); 64 return getName(nativeHandle_); 65 } 66 67 /** 68 * Gets the ID of the Column Family. 69 * 70 * @return the ID of the Column Family. 71 */ getID()72 public int getID() { 73 assert(isOwningHandle() || isDefaultColumnFamily()); 74 return getID(nativeHandle_); 75 } 76 77 /** 78 * Gets the up-to-date descriptor of the column family 79 * associated with this handle. Since it fills "*desc" with the up-to-date 80 * information, this call might internally lock and release DB mutex to 81 * access the up-to-date CF options. In addition, all the pointer-typed 82 * options cannot be referenced any longer than the original options exist. 83 * 84 * Note that this function is not supported in RocksDBLite. 85 * 86 * @return the up-to-date descriptor. 87 * 88 * @throws RocksDBException if an error occurs whilst retrieving the 89 * descriptor. 90 */ getDescriptor()91 public ColumnFamilyDescriptor getDescriptor() throws RocksDBException { 92 assert(isOwningHandle() || isDefaultColumnFamily()); 93 return getDescriptor(nativeHandle_); 94 } 95 96 @Override equals(final Object o)97 public boolean equals(final Object o) { 98 if (this == o) { 99 return true; 100 } 101 if (o == null || getClass() != o.getClass()) { 102 return false; 103 } 104 105 final ColumnFamilyHandle that = (ColumnFamilyHandle) o; 106 try { 107 return rocksDB_.nativeHandle_ == that.rocksDB_.nativeHandle_ && 108 getID() == that.getID() && 109 Arrays.equals(getName(), that.getName()); 110 } catch (RocksDBException e) { 111 throw new RuntimeException("Cannot compare column family handles", e); 112 } 113 } 114 115 @Override hashCode()116 public int hashCode() { 117 try { 118 int result = Objects.hash(getID(), rocksDB_.nativeHandle_); 119 result = 31 * result + Arrays.hashCode(getName()); 120 return result; 121 } catch (RocksDBException e) { 122 throw new RuntimeException("Cannot calculate hash code of column family handle", e); 123 } 124 } 125 isDefaultColumnFamily()126 protected boolean isDefaultColumnFamily() { 127 return nativeHandle_ == rocksDB_.getDefaultColumnFamily().nativeHandle_; 128 } 129 130 /** 131 * <p>Deletes underlying C++ iterator pointer.</p> 132 * 133 * <p>Note: the underlying handle can only be safely deleted if the RocksDB 134 * instance related to a certain ColumnFamilyHandle is still valid and 135 * initialized. Therefore {@code disposeInternal()} checks if the RocksDB is 136 * initialized before freeing the native handle.</p> 137 */ 138 @Override disposeInternal()139 protected void disposeInternal() { 140 if(rocksDB_.isOwningHandle()) { 141 disposeInternal(nativeHandle_); 142 } 143 } 144 getName(final long handle)145 private native byte[] getName(final long handle) throws RocksDBException; getID(final long handle)146 private native int getID(final long handle); getDescriptor(final long handle)147 private native ColumnFamilyDescriptor getDescriptor(final long handle) throws RocksDBException; disposeInternal(final long handle)148 @Override protected final native void disposeInternal(final long handle); 149 150 private final RocksDB rocksDB_; 151 } 152