All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.rocksdb.TransactionDB Maven / Gradle / Ivy

Go to download

RocksDB fat jar that contains .so files for linux64, jnilib files for Mac OSX, and a .dll for Windows x64. It contains the Yamcs merge operator for the Parameter Archive

There is a newer version: 9.4.0.11
Show newest version
// Copyright (c) 2011-present, Facebook, Inc.  All rights reserved.
//  This source code is licensed under both the GPLv2 (found in the
//  COPYING file in the root directory) and Apache 2.0 License
//  (found in the LICENSE.Apache file in the root directory).

package org.rocksdb;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 * Database with Transaction support
 */
public class TransactionDB extends RocksDB
    implements TransactionalDB {
  // Field is "used" to prevent GC of the
  @SuppressWarnings("PMD.UnusedPrivateField") private TransactionDBOptions transactionDbOptions_;

  /**
   * Private constructor.
   *
   * @param nativeHandle The native handle of the C++ TransactionDB object
   */
  private TransactionDB(final long nativeHandle) {
    super(nativeHandle);
  }

  /**
   * Open a TransactionDB, similar to {@link RocksDB#open(Options, String)}.
   *
   * @param options {@link org.rocksdb.Options} instance.
   * @param transactionDbOptions {@link org.rocksdb.TransactionDBOptions}
   *     instance.
   * @param path the path to the rocksdb.
   *
   * @return a {@link TransactionDB} instance on success, null if the specified
   *     {@link TransactionDB} can not be opened.
   *
   * @throws RocksDBException if an error occurs whilst opening the database.
   */
  public static TransactionDB open(final Options options,
      final TransactionDBOptions transactionDbOptions, final String path)
      throws RocksDBException {
    final TransactionDB tdb = new TransactionDB(open(options.nativeHandle_,
        transactionDbOptions.nativeHandle_, path));

    // when non-default Options is used, keeping an Options reference
    // in RocksDB can prevent Java to GC during the life-time of
    // the currently-created RocksDB.
    tdb.storeOptionsInstance(options);
    tdb.storeTransactionDbOptions(transactionDbOptions);
    tdb.storeDefaultColumnFamilyHandle(tdb.makeDefaultColumnFamilyHandle());

    return tdb;
  }

  /**
   * Open a TransactionDB, similar to
   * {@link RocksDB#open(DBOptions, String, List, List)}.
   *
   * @param dbOptions {@link org.rocksdb.DBOptions} instance.
   * @param transactionDbOptions {@link org.rocksdb.TransactionDBOptions}
   *     instance.
   * @param path the path to the rocksdb.
   * @param columnFamilyDescriptors list of column family descriptors
   * @param columnFamilyHandles will be filled with ColumnFamilyHandle instances
   *
   * @return a {@link TransactionDB} instance on success, null if the specified
   *     {@link TransactionDB} can not be opened.
   *
   * @throws RocksDBException if an error occurs whilst opening the database.
   */
  public static TransactionDB open(final DBOptions dbOptions,
      final TransactionDBOptions transactionDbOptions,
      final String path,
      final List columnFamilyDescriptors,
      final List columnFamilyHandles)
      throws RocksDBException {
    int defaultColumnFamilyIndex = -1;
    final byte[][] cfNames = new byte[columnFamilyDescriptors.size()][];
    final long[] cfOptionHandles = new long[columnFamilyDescriptors.size()];
    for (int i = 0; i < columnFamilyDescriptors.size(); i++) {
      final ColumnFamilyDescriptor cfDescriptor = columnFamilyDescriptors
          .get(i);
      cfNames[i] = cfDescriptor.getName();
      cfOptionHandles[i] = cfDescriptor.getOptions().nativeHandle_;
      if (Arrays.equals(cfDescriptor.getName(), RocksDB.DEFAULT_COLUMN_FAMILY)) {
        defaultColumnFamilyIndex = i;
      }
    }
    if (defaultColumnFamilyIndex < 0) {
      throw new IllegalArgumentException(
          "You must provide the default column family in your columnFamilyDescriptors");
    }

    final long[] handles = open(dbOptions.nativeHandle_,
        transactionDbOptions.nativeHandle_, path, cfNames, cfOptionHandles);
    final TransactionDB tdb = new TransactionDB(handles[0]);

    // when non-default Options is used, keeping an Options reference
    // in RocksDB can prevent Java to GC during the life-time of
    // the currently-created RocksDB.
    tdb.storeOptionsInstance(dbOptions);
    tdb.storeTransactionDbOptions(transactionDbOptions);

    for (int i = 1; i < handles.length; i++) {
      columnFamilyHandles.add(new ColumnFamilyHandle(tdb, handles[i]));
    }
    tdb.ownedColumnFamilyHandles.addAll(columnFamilyHandles);
    tdb.storeDefaultColumnFamilyHandle(columnFamilyHandles.get(defaultColumnFamilyIndex));

    return tdb;
  }

  /**
   * This is similar to {@link #close()} except that it
   * throws an exception if any error occurs.
   * 

* This will not fsync the WAL files. * If syncing is required, the caller must first call {@link #syncWal()} * or {@link #write(WriteOptions, WriteBatch)} using an empty write batch * with {@link WriteOptions#setSync(boolean)} set to true. *

* See also {@link #close()}. * * @throws RocksDBException if an error occurs whilst closing. */ @Override public void closeE() throws RocksDBException { if (owningHandle_.compareAndSet(true, false)) { try { closeDatabase(nativeHandle_); } finally { disposeInternal(); } } } /** * This is similar to {@link #closeE()} except that it * silently ignores any errors. *

* This will not fsync the WAL files. * If syncing is required, the caller must first call {@link #syncWal()} * or {@link #write(WriteOptions, WriteBatch)} using an empty write batch * with {@link WriteOptions#setSync(boolean)} set to true. *

* See also {@link #close()}. */ @SuppressWarnings("PMD.EmptyCatchBlock") @Override public void close() { for (final ColumnFamilyHandle columnFamilyHandle : // NOPMD - CloseResource ownedColumnFamilyHandles) { columnFamilyHandle.close(); } ownedColumnFamilyHandles.clear(); if (owningHandle_.compareAndSet(true, false)) { try { closeDatabase(nativeHandle_); } catch (final RocksDBException e) { // silently ignore the error report } finally { disposeInternal(); } } } @Override public Transaction beginTransaction(final WriteOptions writeOptions) { return new Transaction(this, beginTransaction(nativeHandle_, writeOptions.nativeHandle_)); } @Override public Transaction beginTransaction(final WriteOptions writeOptions, final TransactionOptions transactionOptions) { return new Transaction(this, beginTransaction(nativeHandle_, writeOptions.nativeHandle_, transactionOptions.nativeHandle_)); } // TODO(AR) consider having beingTransaction(... oldTransaction) set a // reference count inside Transaction, so that we can always call // Transaction#close but the object is only disposed when there are as many // closes as beginTransaction. Makes the try-with-resources paradigm easier for // java developers @Override public Transaction beginTransaction(final WriteOptions writeOptions, final Transaction oldTransaction) { final long jtxnHandle = beginTransaction_withOld(nativeHandle_, writeOptions.nativeHandle_, oldTransaction.nativeHandle_); // RocksJava relies on the assumption that // we do not allocate a new Transaction object // when providing an old_txn assert(jtxnHandle == oldTransaction.nativeHandle_); return oldTransaction; } @Override public Transaction beginTransaction(final WriteOptions writeOptions, final TransactionOptions transactionOptions, final Transaction oldTransaction) { final long jtxn_handle = beginTransaction_withOld(nativeHandle_, writeOptions.nativeHandle_, transactionOptions.nativeHandle_, oldTransaction.nativeHandle_); // RocksJava relies on the assumption that // we do not allocate a new Transaction object // when providing an old_txn assert(jtxn_handle == oldTransaction.nativeHandle_); return oldTransaction; } public Transaction getTransactionByName(final String transactionName) { final long jtxnHandle = getTransactionByName(nativeHandle_, transactionName); if(jtxnHandle == 0) { return null; } final Transaction txn = new Transaction(this, jtxnHandle); // this instance doesn't own the underlying C++ object txn.disOwnNativeHandle(); return txn; } public List getAllPreparedTransactions() { final long[] jtxnHandles = getAllPreparedTransactions(nativeHandle_); final List txns = new ArrayList<>(); for(final long jtxnHandle : jtxnHandles) { final Transaction txn = new Transaction(this, jtxnHandle); // NOPMD - CloseResource // this instance doesn't own the underlying C++ object txn.disOwnNativeHandle(); txns.add(txn); } return txns; } public static class KeyLockInfo { private final String key; private final long[] transactionIDs; private final boolean exclusive; @SuppressWarnings("PMD.ArrayIsStoredDirectly") public KeyLockInfo(final String key, final long[] transactionIDs, final boolean exclusive) { this.key = key; this.transactionIDs = transactionIDs; this.exclusive = exclusive; } /** * Get the key. * * @return the key */ public String getKey() { return key; } /** * Get the Transaction IDs. * * @return the Transaction IDs. */ @SuppressWarnings("PMD.MethodReturnsInternalArray") public long[] getTransactionIDs() { return transactionIDs; } /** * Get the Lock status. * * @return true if the lock is exclusive, false if the lock is shared. */ public boolean isExclusive() { return exclusive; } } /** * Returns map of all locks held. * * @return a map of all the locks held. */ public Map getLockStatusData() { return getLockStatusData(nativeHandle_); } /** * Called from C++ native method {@link #getDeadlockInfoBuffer(long)} * to construct a DeadlockInfo object. * * @param transactionID The transaction id * @param columnFamilyId The id of the {@link ColumnFamilyHandle} * @param waitingKey the key that we are waiting on * @param exclusive true if the lock is exclusive, false if the lock is shared * * @return The waiting transactions */ @SuppressWarnings("PMD.UnusedPrivateMethod") private DeadlockInfo newDeadlockInfo(final long transactionID, final long columnFamilyId, final String waitingKey, final boolean exclusive) { return new DeadlockInfo(transactionID, columnFamilyId, waitingKey, exclusive); } public static class DeadlockInfo { private final long transactionID; private final long columnFamilyId; private final String waitingKey; private final boolean exclusive; private DeadlockInfo(final long transactionID, final long columnFamilyId, final String waitingKey, final boolean exclusive) { this.transactionID = transactionID; this.columnFamilyId = columnFamilyId; this.waitingKey = waitingKey; this.exclusive = exclusive; } /** * Get the Transaction ID. * * @return the transaction ID */ public long getTransactionID() { return transactionID; } /** * Get the Column Family ID. * * @return The column family ID */ public long getColumnFamilyId() { return columnFamilyId; } /** * Get the key that we are waiting on. * * @return the key that we are waiting on */ public String getWaitingKey() { return waitingKey; } /** * Get the Lock status. * * @return true if the lock is exclusive, false if the lock is shared. */ public boolean isExclusive() { return exclusive; } } public static class DeadlockPath { final DeadlockInfo[] path; final boolean limitExceeded; @SuppressWarnings("PMD.ArrayIsStoredDirectly") public DeadlockPath(final DeadlockInfo[] path, final boolean limitExceeded) { this.path = path; this.limitExceeded = limitExceeded; } public boolean isEmpty() { return path.length == 0 && !limitExceeded; } } public DeadlockPath[] getDeadlockInfoBuffer() { return getDeadlockInfoBuffer(nativeHandle_); } public void setDeadlockInfoBufferSize(final int targetSize) { setDeadlockInfoBufferSize(nativeHandle_, targetSize); } private void storeTransactionDbOptions( final TransactionDBOptions transactionDbOptions) { this.transactionDbOptions_ = transactionDbOptions; } @Override protected final void disposeInternal(final long handle) { disposeInternalJni(handle); } private static native void disposeInternalJni(final long handle); private static native long open(final long optionsHandle, final long transactionDbOptionsHandle, final String path) throws RocksDBException; private static native long[] open(final long dbOptionsHandle, final long transactionDbOptionsHandle, final String path, final byte[][] columnFamilyNames, final long[] columnFamilyOptions); private static native void closeDatabase(final long handle) throws RocksDBException; private static native long beginTransaction(final long handle, final long writeOptionsHandle); private static native long beginTransaction( final long handle, final long writeOptionsHandle, final long transactionOptionsHandle); private static native long beginTransaction_withOld( final long handle, final long writeOptionsHandle, final long oldTransactionHandle); private static native long beginTransaction_withOld(final long handle, final long writeOptionsHandle, final long transactionOptionsHandle, final long oldTransactionHandle); private static native long getTransactionByName(final long handle, final String name); private static native long[] getAllPreparedTransactions(final long handle); private static native Map getLockStatusData(final long handle); private static native DeadlockPath[] getDeadlockInfoBuffer(final long handle); private static native void setDeadlockInfoBufferSize(final long handle, final int targetSize); }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy