/**
   * Get a locker for a read or cursor operation.
   *
   * @throws IllegalArgumentException via db/cursor read/write methods.
   */
  public static Locker getReadableLocker(
      Environment env,
      Transaction userTxn,
      boolean dbIsTransactional,
      boolean readCommittedIsolation)
      throws DatabaseException {

    if (userTxn != null && !dbIsTransactional) {
      throw new IllegalArgumentException(
          "A Transaction cannot be used because the" + " database was opened non-transactionally");
    }

    Locker locker = null;
    if (userTxn != null) {

      /*
       * Use the locker for the given transaction.  Request read-comitted
       * if that isolation level is configured for the transaction, or if
       * true is passed for the parameter (this is the case when
       * read-committed is configured for the cursor).
       */
      locker = DbInternal.getLocker(userTxn);
      if (locker.isReadCommittedIsolation()) {
        readCommittedIsolation = true;
      }
    }

    return getReadableLocker(env, locker, readCommittedIsolation);
  }
  /** @throws Exception */
  @Test
  public void testSerialization() throws Exception {
    // a simple worker that acquires a lock on page 5
    class Locker extends Thread {
      private final PageAccessSynchronizer sync;

      public Locker(PageAccessSynchronizer sync) {
        this.sync = sync;
      }

      @Override
      public void run() {
        sync.lockPage(5);
      }
    }

    // set up a synchronizer and lock page 5 with locker1
    final Duration timeout = Duration.seconds(30);
    final PageAccessSynchronizer sync = new PageAccessSynchronizer(timeout);
    Locker locker1 = new Locker(sync);

    final long start = System.currentTimeMillis();
    locker1.run();

    // make sure we can serialize the synchronizer

    final PageAccessSynchronizer sync2 = WicketObjects.cloneObject(sync);
    assertTrue(sync != sync2);

    // make sure the clone does not retain locks by attempting to lock page locked by locker1 in
    // locker2
    Locker locker2 = new Locker(sync2);
    locker2.run();
    assertTrue(Duration.milliseconds(System.currentTimeMillis() - start).lessThan(timeout));
  }
  /**
   * Get a locker for this database handle for a read or cursor operation.
   *
   * @throws IllegalArgumentException via db/cursor read/write methods.
   */
  public static Locker getReadableLocker(
      Environment env, Database dbHandle, Locker locker, boolean readCommittedIsolation)
      throws DatabaseException {

    DatabaseImpl dbImpl = DbInternal.getDatabaseImpl(dbHandle);
    if (!dbImpl.isTransactional() && locker != null && locker.isTransactional()) {
      throw new IllegalArgumentException(
          "A Transaction cannot be used because the" + " database was opened non-transactionally");
    }

    /* Don't reuse a non-transactional locker. */
    if (locker != null && !locker.isTransactional()) {
      locker = null;
    }

    /*
     * Request read-comitted if that isolation level is configured for the
     * locker being reused, or if true is passed for the parameter (this is
     * the case when read-committed is configured for the cursor).
     */
    if (locker != null && locker.isReadCommittedIsolation()) {
      readCommittedIsolation = true;
    }

    return getReadableLocker(env, locker, readCommittedIsolation);
  }
  // tests statistic of SMPP load balancer
  @Test
  public void testStatisticVariable() {
    int clientNumbers = 3;
    clientHandlerArray = new DefaultSmppClientHandler[clientNumbers];
    int smsNumber = 1;
    Locker locker = new Locker(clientNumbers);

    for (int i = 0; i < clientNumbers; i++) new Load(i, smsNumber, locker).start();

    try {
      Thread.sleep(2000);
    } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    activeConnections = balancer.getNumberOfActiveSmppConnections();
    locker.waitForClients();
    assertEquals(348, balancer.getNumberOfSmppBytesToServer());
    assertEquals(198, balancer.getNumberOfSmppBytesToClient());
    assertEquals(clientNumbers * 3, balancer.getNumberOfSmppRequestsToServer());
    assertEquals(
        clientNumbers, balancer.getSmppRequestsProcessedById(SmppConstants.CMD_ID_SUBMIT_SM));
    assertEquals(
        clientNumbers, balancer.getSmppResponsesProcessedById(SmppConstants.CMD_ID_SUBMIT_SM_RESP));
    assertEquals(clientNumbers * 2, activeConnections);
  }
Example #5
0
  /**
   * Release a lock and possibly notify any waiters that they have been granted the lock.
   *
   * @param nodeId The node ID of the lock to release.
   * @return true if the lock is released successfully, false if the lock is not currently being
   *     held.
   */
  public boolean release(long nodeId, Locker locker) throws DatabaseException {

    synchronized (locker) {
      Set<Locker> newOwners = releaseAndFindNotifyTargets(nodeId, locker);

      if (newOwners == null) {
        return false;
      }

      if (newOwners.size() > 0) {

        /*
         * There is a new set of owners and/or there are restart
         * waiters that should be notified.
         */
        Iterator<Locker> iter = newOwners.iterator();

        while (iter.hasNext()) {
          Locker lockerToNotify = iter.next();

          /* Use notifyAll to support multiple threads per txn. */
          synchronized (lockerToNotify) {
            lockerToNotify.notifyAll();
          }

          assert EnvironmentImpl.maybeForceYield();
        }
      }

      return true;
    }
  }
  protected void assertThreadNotFailed(final Locker t) {
    final Throwable throwable = t.getThrowable();

    if (throwable != null) {
      assertThat(t.getName() + " failed with: " + throwable.getMessage(), false);
    }
  }
Example #7
0
 @Test
 public void testAddToDictionary() throws UnsupportedEncodingException, NoSuchAlgorithmException {
   byte[] chunk1 = new byte[1024];
   String hash = testlocker.md5ToString(testlocker.md5(chunk1));
   testlocker.addToDictionary(hash, chunk1);
   Assert.assertTrue(testlocker.dictionary.contains(chunk1));
   Assert.assertTrue(testlocker.dictionary.containsKey(hash));
 }
Example #8
0
 @Test
 public void testcontentsMatch() throws UnsupportedEncodingException, NoSuchAlgorithmException {
   byte[] chunk2 = new byte[1024];
   String hash = testlocker.md5ToString(testlocker.md5(chunk2));
   String hash2 = hash + "false";
   testlocker.addToDictionary(hash, chunk2);
   Assert.assertTrue(testlocker.contentsMatch(hash, chunk2));
   Assert.assertFalse(testlocker.contentsMatch(hash2, chunk2));
 }
 @Test
 public void testRebind() {
   Locker locker = new Locker(clientNumbers);
   // start client
   new Load(locker, 2).start();
   locker.waitForClients();
   boolean isCorrectEnqLinkRequest = false;
   for (DefaultSmppServerHandler handler : serverHandlerArray)
     if (handler.getSmsNumber() == 6) isCorrectEnqLinkRequest = true;
   assertTrue(isCorrectEnqLinkRequest);
 }
  /** @see LockManager#getTimeoutInfo */
  @Override
  TimeoutInfo getTimeoutInfo(
      boolean isLockNotTxnTimeout,
      Locker locker,
      long lsn,
      LockType type,
      LockGrantType grantType,
      Lock useLock,
      long timeout,
      long start,
      long now,
      DatabaseImpl database)
      throws DatabaseException {

    if (locker.lockingRequired()) {
      return superiorLockManager.getTimeoutInfo(
          isLockNotTxnTimeout,
          locker,
          lsn,
          type,
          grantType,
          useLock,
          timeout,
          start,
          now,
          database);
    }
    return null;
  }
Example #11
0
 public static Locker getWritableLocker__wrappee__base(
     Environment env,
     Transaction userTxn,
     boolean dbIsTransactional,
     boolean retainNonTxnLocks,
     TransactionConfig autoCommitConfig)
     throws DatabaseException {
   EnvironmentImpl envImpl = DbInternal.envGetEnvironmentImpl(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 new AutoTxn(envImpl, autoCommitConfig);
   } else if (userTxn == null) {
     if (retainNonTxnLocks) {
       return new BasicLocker(envImpl);
     } else {
       return new ThreadLocker(envImpl);
     }
   } else {
     if (!envIsTransactional) {
       throw new DatabaseException(
           "A Transaction cannot be used because the"
               + " environment was opened"
               + " non-transactionally");
     }
     if (!dbIsTransactional) {
       throw new DatabaseException(
           "A Transaction cannot be used because the"
               + " database was opened"
               + " non-transactionally");
     }
     Locker locker = DbInternal.getLocker(userTxn);
     if (locker.isReadCommittedIsolation() && !retainNonTxnLocks) {
       return new ReadCommittedLocker(envImpl, locker);
     } else {
       return locker;
     }
   }
 }
Example #12
0
 @Test
 public void testgetSizeOfLocker() {
   int size = 0;
   for (FileInfo f : testlocker.files) {
     size += f.getSize();
   }
   Assert.assertEquals(size, testlocker.getSizeOfLocker());
 }
Example #13
0
  @Test
  public void testgetSizeOfDB() throws IOException {

    RandomAccessFile locker1 = new RandomAccessFile("locker.txt", "r");
    FileChannel l = locker1.getChannel();
    long dbSize = l.size();
    Assert.assertEquals(testlocker.getSizeOfDB(), dbSize);
  }
Example #14
0
  /**
   * Attempt to acquire a lock of <i>type</i> on <i>nodeId</i>. If the lock acquisition would result
   * in a deadlock, throw an exception.<br>
   * If the requested lock is not currently available, block until it is or until timeout
   * milliseconds have elapsed.<br>
   * If a lock of <i>type</i> is already held, return EXISTING.<br>
   * If a WRITE lock is held and a READ lock is requested, return PROMOTION.<br>
   * If a lock request is for a lock that is not currently held, return either NEW or DENIED
   * depending on whether the lock is granted or not.<br>
   *
   * @param nodeId The NodeId to lock.
   * @param locker The Locker to lock this on behalf of.
   * @param type The lock type requested.
   * @param timeout milliseconds to time out after if lock couldn't be obtained. 0 means block
   *     indefinitely. Not used if nonBlockingRequest is true.
   * @param nonBlockingRequest if true, means don't block if lock can't be acquired, and ignore the
   *     timeout parameter.
   * @return a LockGrantType indicating whether the request was fulfilled or not. LockGrantType.NEW
   *     means the lock grant was fulfilled and the caller did not previously hold the lock.
   *     PROMOTION means the lock was granted and it was a promotion from READ to WRITE. EXISTING
   *     means the lock was already granted (not a promotion). DENIED means the lock was not granted
   *     because the timeout passed without acquiring the lock or timeout was 0 and the lock was not
   *     immediately available.
   * @throws LockConflictException if lock could not be acquired.
   * @throws IllegalArgumentException via db/cursor read/write methods, if non-transactional access
   *     to a replicated environment is attempted, and read-uncommitted is not specified.
   */
  public LockGrantType lock(
      long nodeId,
      Locker locker,
      LockType type,
      long timeout,
      boolean nonBlockingRequest,
      DatabaseImpl database)
      throws LockConflictException, DatabaseException {

    assert timeout >= 0;

    /* No lock needed for dirty-read, return as soon as possible. */
    if (type == LockType.NONE) {
      return LockGrantType.NONE_NEEDED;
    }

    /*
     * Assert that a replication-defined locker is used for locks on
     * replicated databases.  Two cases are exempt from this rule:
     * - Only NameLNs that identify replicated DBs are replicated, not
     *   all NameLNs in the naming DB, so the naming DB is exempt.
     * - Non-preemption is permissible for selected internal operations
     *   because we can ensure that they are not long running and will not
     *   hold locks interminably.  A BasicLocker is often used internally
     *   in such cases.
     */
    if (envImpl.isReplicated()
        && database != null
        && database.isReplicated()
        && !database.getId().equals(DbTree.NAME_DB_ID)
        && (locker.getPreemptable() || type.isWriteLock())
        && !locker.isReplicationDefined()) {
      throw EnvironmentFailureException.unexpectedState("Locker: " + locker.getClass().getName());
    }

    /*
     * Lock on locker before latching the lockTable to avoid having another
     * notifier perform the notify before the waiter is actually waiting.
     */
    synchronized (locker) {
      LockGrantType ret = null;
      ret = lockInternal(nodeId, locker, type, timeout, nonBlockingRequest, database);
      return ret;
    }
  }
  /** @see LockManager#demote */
  @Override
  void demote(long lsn, Locker locker) throws DatabaseException {

    if (locker.lockingRequired()) {
      superiorLockManager.demote(lsn, locker);
    } else {
      return;
    }
  }
  /** @see LockManager#stealLock */
  @Override
  public LockAttemptResult stealLock(Long lsn, Locker locker, LockType lockType)
      throws DatabaseException {

    if (locker.lockingRequired()) {
      return superiorLockManager.stealLock(lsn, locker, lockType);
    }
    return null;
  }
  /** @see LockManager#validateOwnership */
  @Override
  boolean validateOwnership(
      Long lsn, Locker locker, LockType type, boolean flushFromWaiters, MemoryBudget mb)
      throws DatabaseException {

    if (locker.lockingRequired()) {
      return superiorLockManager.validateOwnership(lsn, locker, type, flushFromWaiters, mb);
    }
    return true;
  }
Example #18
0
 public static Locker getReadableLocker__wrappee__base(
     Environment env,
     Transaction userTxn,
     boolean dbIsTransactional,
     boolean retainNonTxnLocks,
     boolean readCommittedIsolation)
     throws DatabaseException {
   if (userTxn != null && !dbIsTransactional) {
     throw new DatabaseException(
         "A Transaction cannot be used because the"
             + " database was opened"
             + " non-transactionally");
   }
   Locker locker = null;
   if (userTxn != null) {
     locker = DbInternal.getLocker(userTxn);
     if (locker.isReadCommittedIsolation()) {
       readCommittedIsolation = true;
     }
   }
   return getReadableLocker(env, locker, retainNonTxnLocks, readCommittedIsolation);
 }
Example #19
0
 public static Locker getReadableLocker__wrappee__base(
     Environment env,
     Database dbHandle,
     Locker locker,
     boolean retainNonTxnLocks,
     boolean readCommittedIsolation)
     throws DatabaseException {
   DatabaseImpl dbImpl = DbInternal.dbGetDatabaseImpl(dbHandle);
   if (!dbImpl.isTransactional() && locker != null && locker.isTransactional()) {
     throw new DatabaseException(
         "A Transaction cannot be used because the"
             + " database was opened"
             + " non-transactionally");
   }
   if (locker != null && !locker.isTransactional() && !retainNonTxnLocks) {
     locker = null;
   }
   if (locker != null && locker.isReadCommittedIsolation()) {
     readCommittedIsolation = true;
   }
   return getReadableLocker(env, locker, retainNonTxnLocks, readCommittedIsolation);
 }
Example #20
0
  private StringBuilder findDeadlock1(Set<Locker> ownerSet, Lock lock, Locker rootLocker) {

    Iterator<LockInfo> ownerIter = lock.getOwnersClone().iterator();
    while (ownerIter.hasNext()) {
      LockInfo info = ownerIter.next();
      Locker locker = info.getLocker();
      Lock waitsFor = locker.getWaitingFor();
      if (ownerSet.contains(locker) || locker == rootLocker) {
        /* Found a cycle. */
        StringBuilder ret = new StringBuilder();
        ret.append("Transaction ").append(locker.toString());
        ret.append(" owns LockAddr:").append(System.identityHashCode(lock));
        ret.append(" ").append(info).append("\n");
        ret.append("Transaction ").append(locker.toString());
        ret.append(" waits for");
        if (waitsFor == null) {
          ret.append(" nothing");
        } else {
          ret.append(" LockAddr:");
          ret.append(System.identityHashCode(waitsFor));
        }
        ret.append("\n");
        return ret;
      }
      if (waitsFor != null) {
        ownerSet.add(locker);
        StringBuilder sb = findDeadlock1(ownerSet, waitsFor, rootLocker);
        if (sb != null) {
          String waitInfo = "Transaction " + locker + " waits for " + waitsFor + "\n";
          sb.insert(0, waitInfo);
          return sb;
        }
        ownerSet.remove(locker); // is this necessary?
      }
    }

    return null;
  }
Example #21
0
 protected void hook820(StatsConfig config, TransactionStats stats) throws DatabaseException {
   stats.setNCommits(numCommits);
   stats.setNAborts(numAborts);
   stats.setNXAPrepares(numXAPrepares);
   stats.setNXACommits(numXACommits);
   stats.setNXAAborts(numXAAborts);
   stats.setNActive(allTxns.size());
   TransactionStats.Active[] activeSet = new TransactionStats.Active[stats.getNActive()];
   stats.setActiveTxns(activeSet);
   Iterator iter = allTxns.iterator();
   int i = 0;
   while (iter.hasNext()) {
     Locker txn = (Locker) iter.next();
     activeSet[i] = new TransactionStats.Active(txn.toString(), txn.getId(), 0);
     i++;
   }
   if (config.getClear()) {
     numCommits = 0;
     numAborts = 0;
     numXACommits = 0;
     numXAAborts = 0;
   }
 }
  /** @see LockManager#attemptLock */
  @Override
  LockAttemptResult attemptLock(
      Long lsn,
      Locker locker,
      LockType type,
      boolean nonBlockingRequest,
      boolean jumpAheadOfWaiters)
      throws DatabaseException {

    if (locker.lockingRequired()) {
      return superiorLockManager.attemptLock(
          lsn, locker, type, nonBlockingRequest, jumpAheadOfWaiters);
    }
    return new LockAttemptResult(null, LockGrantType.NEW, true);
  }
Example #23
0
  LockAttemptResult attemptLockInternal(
      Long nodeId, Locker locker, LockType type, boolean nonBlockingRequest, int lockTableIndex)
      throws DatabaseException {

    nRequests.increment();

    /* Get the target lock. */
    Map<Long, Lock> lockTable = lockTables[lockTableIndex];
    Lock useLock = lockTable.get(nodeId);
    if (useLock == null) {
      useLock = new ThinLockImpl();
      lockTable.put(nodeId, useLock);
      memoryBudget.updateLockMemoryUsage(TOTAL_THINLOCKIMPL_OVERHEAD, lockTableIndex);
    }

    /*
     * Attempt to lock.  Possible return values are NEW, PROMOTION, DENIED,
     * EXISTING, WAIT_NEW, WAIT_PROMOTION, WAIT_RESTART.
     */
    LockAttemptResult lar =
        useLock.lock(type, locker, nonBlockingRequest, memoryBudget, lockTableIndex);
    if (lar.useLock != useLock) {
      /* The lock mutated from ThinLockImpl to LockImpl. */
      useLock = lar.useLock;
      lockTable.put(nodeId, useLock);
      /* We still have the overhead of the hashtable (locktable). */
      memoryBudget.updateLockMemoryUsage(THINLOCK_MUTATE_OVERHEAD, lockTableIndex);
    }
    LockGrantType lockGrant = lar.lockGrant;
    boolean success = false;

    /* Was the attempt successful? */
    if ((lockGrant == LockGrantType.NEW) || (lockGrant == LockGrantType.PROMOTION)) {
      locker.addLock(nodeId, type, lockGrant);
      success = true;
    } else if (lockGrant == LockGrantType.EXISTING) {
      success = true;
    } else if (lockGrant == LockGrantType.DENIED) {
      /* Locker.lock will throw LockNotAvailableException. */
    } else {
      nWaits.increment();
    }
    return new LockAttemptResult(useLock, lockGrant, success);
  }
Example #24
0
  /** Do the real work of transfer */
  void transferInternal(
      long nodeId, Locker owningLocker, Locker destLocker, boolean demoteToRead, int lockTableIndex)
      throws DatabaseException {

    Map<Long, Lock> lockTable = lockTables[lockTableIndex];
    Lock useLock = lockTable.get(Long.valueOf(nodeId));

    assert useLock != null : "Transfer, lock " + nodeId + " was null";
    if (demoteToRead) {
      useLock.demote(owningLocker);
    }
    Lock newLock = useLock.transfer(nodeId, owningLocker, destLocker, memoryBudget, lockTableIndex);
    if (newLock != useLock) {
      /* The lock mutated from ThinLockImpl to LockImpl. */
      lockTable.put(nodeId, newLock);
      /* We still have the overhead of the hashtable (locktable). */
      memoryBudget.updateLockMemoryUsage(THINLOCK_MUTATE_OVERHEAD, lockTableIndex);
    }
    owningLocker.removeLock(nodeId);
  }
Example #25
0
 protected void hook296(Locker locker, NameLockResult result, DatabaseImpl newDb)
     throws DatabaseException, CloneNotSupportedException {
   locker.markDeleteAtTxnEnd(result.dbImpl, true);
   locker.markDeleteAtTxnEnd(newDb, false);
   original(locker, result, newDb);
 }
Example #26
0
 protected void hook297(Locker locker, DatabaseImpl oldDatabase)
     throws DatabaseException, CloneNotSupportedException, UnsupportedEncodingException {
   locker.markDeleteAtTxnEnd(oldDatabase, true);
   original(locker, oldDatabase);
 }
Example #27
0
 @Test
 public void testHashExists() {
   byte[] chunk1 = new byte[1024];
   testlocker.dictionary.put("1", chunk1);
   Assert.assertEquals(testlocker.hashExists("1"), testlocker.dictionary.containsKey("1"));
 }
  /**
   * 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;
    }
  }
Example #29
0
 @Test
 public void tetGetProgress() {
   Assert.assertEquals(testlocker.getProgress(), testlocker.progress);
 }
Example #30
0
 @Test(expected = FileNotFoundException.class)
 public void testDynamicBlockInsert() {
   testlocker.dynamicBlockInsert("nosuchfile");
 }