/*
   * Copy all collections that will be needed to convert masterTxn to this
   * ReplayTxn. Note that we do not need to copy the openDatabaseHandle
   * collection.  That collection is only needed by an application-facing
   * Txn, so that those database handles can be invalidated if
   * needed. ReplayTxn is not application-facing, and uses DatabaseImpls
   * rather than Databases.
   */
  public void copyDatabasesForConversion(Txn masterTxn) {
    if (masterTxn.getUndoDatabases() != null) {
      if (undoDatabases == null) {
        undoDatabases = new HashMap<DatabaseId, DatabaseImpl>();
      }
      undoDatabases.putAll(masterTxn.getUndoDatabases());
    }

    if (masterTxn.getDeletedDatabases() != null) {
      if (deletedDatabases == null) {
        deletedDatabases = new HashSet<DatabaseCleanupInfo>();
      }
      deletedDatabases.addAll(masterTxn.getDeletedDatabases());
    }
  }
Example #2
0
  @Override
  protected void close(boolean isCommit) throws DatabaseException {

    super.close(isCommit);

    if (activeTxns != null) {
      Txn removed = activeTxns.remove(getId());
      assert removed != null : "txn was not in map " + this + " " + LoggerUtils.getStackTrace();
    }
  }
  /**
   * Get a locker for a write operation.
   *
   * @param autoTxnIsReplicated is true if this transaction is executed on a rep group master, and
   *     needs to be broadcast. Currently, all application-created transactions are of the type
   *     com.sleepycat.je.txn.Txn, and are replicated if the parent environment is replicated. Auto
   *     Txns are trickier because they may be created for a local write operation, such as log
   *     cleaning.
   * @throws IllegalArgumentException via db/cursor read/write methods.
   */
  public static Locker getWritableLocker(
      Environment env,
      Transaction userTxn,
      boolean isInternalDb,
      boolean dbIsTransactional,
      boolean autoTxnIsReplicated,
      TransactionConfig autoCommitConfig)
      throws DatabaseException {

    EnvironmentImpl envImpl = DbInternal.getEnvironmentImpl(env);
    boolean envIsTransactional = envImpl.isTransactional();

    if (userTxn == null) {
      Transaction xaLocker = env.getThreadTransaction();
      if (xaLocker != null) {
        return DbInternal.getLocker(xaLocker);
      }
    }

    if (dbIsTransactional && userTxn == null) {

      if (autoCommitConfig == null) {
        autoCommitConfig = DbInternal.getDefaultTxnConfig(env);
      }

      return Txn.createAutoTxn(
          envImpl,
          autoCommitConfig,
          (autoTxnIsReplicated ? ReplicationContext.MASTER : ReplicationContext.NO_REPLICATE));

    } else if (userTxn == null) {
      /* Non-transactional user operations use ThreadLocker. */
      return ThreadLocker.createThreadLocker(envImpl);
    } else {

      /*
       * The user provided a transaction, the environment and the
       * database had better be opened transactionally.
       */
      if (!isInternalDb && !envIsTransactional) {
        throw new IllegalArgumentException(
            "A Transaction cannot be used because the"
                + " environment was opened non-transactionally");
      }
      if (!dbIsTransactional) {
        throw new IllegalArgumentException(
            "A Transaction cannot be used because the"
                + " database was opened non-transactionally");
      }

      /*
       * Use the locker for the given transaction.  For read-comitted,
       * wrap the given transactional locker in a special locker for that
       * isolation level.
       */
      Locker locker = DbInternal.getLocker(userTxn);
      if (locker.isReadCommittedIsolation()) {
        return ReadCommittedLocker.createReadCommittedLocker(envImpl, locker);
      }

      return locker;
    }
  }