/** * 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); }
/** * 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); } }
@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)); }
@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; }
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; } } }
@Test public void testgetSizeOfLocker() { int size = 0; for (FileInfo f : testlocker.files) { size += f.getSize(); } Assert.assertEquals(size, testlocker.getSizeOfLocker()); }
@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); }
/** * 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; }
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); }
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); }
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; }
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); }
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); }
/** 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); }
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); }
protected void hook297(Locker locker, DatabaseImpl oldDatabase) throws DatabaseException, CloneNotSupportedException, UnsupportedEncodingException { locker.markDeleteAtTxnEnd(oldDatabase, true); original(locker, oldDatabase); }
@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; } }
@Test public void tetGetProgress() { Assert.assertEquals(testlocker.getProgress(), testlocker.progress); }
@Test(expected = FileNotFoundException.class) public void testDynamicBlockInsert() { testlocker.dynamicBlockInsert("nosuchfile"); }