Search in sources :

Example 1 with LockMode

use of com.palantir.lock.LockMode in project atlasdb by palantir.

the class SnapshotTransactionTest method getExpiredHeldLocksToken.

private HeldLocksToken getExpiredHeldLocksToken() {
    ImmutableSortedMap.Builder<LockDescriptor, LockMode> builder = ImmutableSortedMap.naturalOrder();
    builder.put(AtlasRowLockDescriptor.of(TransactionConstants.TRANSACTION_TABLE.getQualifiedName(), TransactionConstants.getValueForTimestamp(0L)), LockMode.WRITE);
    long creationDateMs = System.currentTimeMillis();
    long expirationDateMs = creationDateMs - 1;
    TimeDuration lockTimeout = SimpleTimeDuration.of(0, TimeUnit.SECONDS);
    long versionId = 0L;
    return new HeldLocksToken(BigInteger.ZERO, lockClient, creationDateMs, expirationDateMs, LockCollections.of(builder.build()), lockTimeout, versionId, "Dummy thread");
}
Also used : AtlasRowLockDescriptor(com.palantir.lock.AtlasRowLockDescriptor) LockDescriptor(com.palantir.lock.LockDescriptor) HeldLocksToken(com.palantir.lock.HeldLocksToken) ImmutableSortedMap(com.google.common.collect.ImmutableSortedMap) SimpleTimeDuration(com.palantir.lock.SimpleTimeDuration) TimeDuration(com.palantir.lock.TimeDuration) LockMode(com.palantir.lock.LockMode)

Example 2 with LockMode

use of com.palantir.lock.LockMode in project atlasdb by palantir.

the class LockServiceImpl method changeOwner.

private void changeOwner(LockCollection<? extends ClientAwareReadWriteLock> locks, LockClient oldClient, LockClient newClient) {
    Preconditions.checkArgument((oldClient == INTERNAL_LOCK_GRANT_CLIENT) != (newClient == INTERNAL_LOCK_GRANT_CLIENT));
    Collection<KnownClientLock> locksToRollback = Lists.newLinkedList();
    try {
        for (Entry<? extends ClientAwareReadWriteLock, LockMode> entry : locks.entries()) {
            ClientAwareReadWriteLock lock = entry.getKey();
            LockMode mode = entry.getValue();
            lock.get(oldClient, mode).changeOwner(newClient);
            locksToRollback.add(lock.get(newClient, mode));
        }
        locksToRollback.clear();
    } finally {
        /*
             * The above call to KnownLockClient.changeOwner() could throw an
             * IllegalMonitorStateException if we are CREATING a lock grant, but
             * it will never throw if we're changing the owner FROM the internal
             * lock grant client TO some named or anonymous client. This is true
             * because the internal lock grant client never increments the read
             * or write hold counts.
             *
             * In other words, if a lock has successfully made it into the grant
             * state (because the client didn't hold both the read lock and the
             * write lock, and didn't hold the write lock multiple times), then
             * these same conditions cannot possibly be violated between that
             * time and the time that the rollback operation below is performed.
             *
             * In conclusion, if this method is being called from
             * convertToGrant(), then the call to changeOwner() below will not
             * throw an exception, whereas if this method is being called from
             * useGrant(), then the try block above will not throw an exception,
             * which makes this finally block a no-op.
             */
        for (KnownClientLock lock : locksToRollback) {
            lock.changeOwner(oldClient);
        }
    }
}
Also used : LockMode(com.palantir.lock.LockMode)

Example 3 with LockMode

use of com.palantir.lock.LockMode in project atlasdb by palantir.

the class AssertLockedKeyValueService method put.

@Override
public void put(TableReference tableRef, Map<Cell, byte[]> values, long timestamp) {
    if (tableRef.equals(TransactionConstants.TRANSACTION_TABLE)) {
        SortedMap<LockDescriptor, LockMode> mapToAssertLockHeld = Maps.newTreeMap();
        SortedMap<LockDescriptor, LockMode> mapToAssertLockNotHeld = Maps.newTreeMap();
        for (Map.Entry<Cell, byte[]> e : values.entrySet()) {
            LockDescriptor descriptor = AtlasRowLockDescriptor.of(tableRef.getQualifiedName(), e.getKey().getRowName());
            if (Arrays.equals(e.getValue(), TransactionConstants.getValueForTimestamp(TransactionConstants.FAILED_COMMIT_TS))) {
                mapToAssertLockNotHeld.put(descriptor, LockMode.READ);
            } else {
                mapToAssertLockHeld.put(descriptor, LockMode.READ);
            }
        }
        try {
            if (!mapToAssertLockHeld.isEmpty()) {
                LockRequest request = LockRequest.builder(mapToAssertLockHeld).doNotBlock().lockAsManyAsPossible().build();
                LockRefreshToken lock = lockService.lock(LockClient.ANONYMOUS.getClientId(), request);
                Validate.isTrue(lock == null, "these should already be held");
            }
            if (!mapToAssertLockNotHeld.isEmpty()) {
                LockRequest request = LockRequest.builder(mapToAssertLockNotHeld).doNotBlock().build();
                LockRefreshToken lock = lockService.lock(LockClient.ANONYMOUS.getClientId(), request);
                Validate.isTrue(lock != null, "these should already be waited for");
            }
        } catch (InterruptedException e) {
            throw Throwables.throwUncheckedException(e);
        }
    }
    super.put(tableRef, values, timestamp);
}
Also used : AtlasRowLockDescriptor(com.palantir.lock.AtlasRowLockDescriptor) LockDescriptor(com.palantir.lock.LockDescriptor) LockMode(com.palantir.lock.LockMode) Map(java.util.Map) SortedMap(java.util.SortedMap) Cell(com.palantir.atlasdb.keyvalue.api.Cell) LockRequest(com.palantir.lock.LockRequest) LockRefreshToken(com.palantir.lock.LockRefreshToken)

Example 4 with LockMode

use of com.palantir.lock.LockMode in project atlasdb by palantir.

the class LockServiceImpl method lockWithFullLockResponse.

@Override
public // We're concerned about sanitizing logs at the info level and above. This method just logs at debug and info.
LockResponse lockWithFullLockResponse(LockClient client, LockRequest request) throws InterruptedException {
    Preconditions.checkNotNull(client);
    Preconditions.checkArgument(!client.equals(INTERNAL_LOCK_GRANT_CLIENT));
    Preconditions.checkArgument(request.getLockTimeout().compareTo(maxAllowedLockTimeout) <= 0, "Requested lock timeout (%s) is greater than maximum allowed lock timeout (%s)", request.getLockTimeout(), maxAllowedLockTimeout);
    long startTime = System.currentTimeMillis();
    if (requestLogger.isDebugEnabled()) {
        requestLogger.debug("LockServiceImpl processing lock request {} for requesting thread {}", UnsafeArg.of("lockRequest", request), SafeArg.of("requestingThread", request.getCreatingThreadName()));
    }
    Map<ClientAwareReadWriteLock, LockMode> locks = Maps.newLinkedHashMap();
    if (isShutDown.get()) {
        throw new ServiceNotAvailableException("This lock server is shut down.");
    }
    try {
        boolean indefinitelyBlocking = isIndefinitelyBlocking(request.getBlockingMode());
        if (indefinitelyBlocking) {
            indefinitelyBlockingThreads.add(Thread.currentThread());
        }
        outstandingLockRequestMultimap.put(client, request);
        Map<LockDescriptor, LockClient> failedLocks = Maps.newHashMap();
        @Nullable Long deadline = (request.getBlockingDuration() == null) ? null : System.nanoTime() + request.getBlockingDuration().toNanos();
        if (request.getBlockingMode() == BLOCK_UNTIL_TIMEOUT) {
            if (request.getLockGroupBehavior() == LOCK_AS_MANY_AS_POSSIBLE) {
                tryLocks(client, request, DO_NOT_BLOCK, null, LOCK_AS_MANY_AS_POSSIBLE, locks, failedLocks);
            }
        }
        tryLocks(client, request, request.getBlockingMode(), deadline, request.getLockGroupBehavior(), locks, failedLocks);
        if (request.getBlockingMode() == BlockingMode.BLOCK_INDEFINITELY_THEN_RELEASE) {
            if (log.isTraceEnabled()) {
                logNullResponse(client, request, null);
            }
            if (requestLogger.isDebugEnabled()) {
                requestLogger.debug("Timed out requesting {} for requesting thread {} after {} ms", UnsafeArg.of("request", request), SafeArg.of("threadName", request.getCreatingThreadName()), SafeArg.of("timeoutMillis", System.currentTimeMillis() - startTime));
            }
            return new LockResponse(failedLocks);
        }
        if (locks.isEmpty() || ((request.getLockGroupBehavior() == LOCK_ALL_OR_NONE) && (locks.size() < request.getLockDescriptors().size()))) {
            if (log.isTraceEnabled()) {
                logNullResponse(client, request, null);
            }
            if (requestLogger.isDebugEnabled()) {
                requestLogger.debug("Failed to acquire all locks for {} for requesting thread {} after {} ms", UnsafeArg.of("request", request), SafeArg.of("threadName", request.getCreatingThreadName()), SafeArg.of("waitMillis", System.currentTimeMillis() - startTime));
            }
            if (requestLogger.isTraceEnabled()) {
                logLockAcquisitionFailure(failedLocks);
            }
            return new LockResponse(null, failedLocks);
        }
        Builder<LockDescriptor, LockMode> lockDescriptorMap = ImmutableSortedMap.naturalOrder();
        for (Entry<ClientAwareReadWriteLock, LockMode> entry : locks.entrySet()) {
            lockDescriptorMap.put(entry.getKey().getDescriptor(), entry.getValue());
        }
        if (request.getVersionId() != null) {
            versionIdMap.put(client, request.getVersionId());
        }
        HeldLocksToken token = createHeldLocksToken(client, LockCollections.of(lockDescriptorMap.build()), LockCollections.of(locks), request.getLockTimeout(), request.getVersionId(), request.getCreatingThreadName());
        locks.clear();
        if (log.isTraceEnabled()) {
            logNullResponse(client, request, token);
        }
        if (Thread.interrupted()) {
            throw new InterruptedException("Interrupted while locking.");
        }
        if (requestLogger.isDebugEnabled()) {
            requestLogger.debug("Successfully acquired locks {} for requesting thread {} after {} ms", UnsafeArg.of("request", request), SafeArg.of("threadName", request.getCreatingThreadName()), SafeArg.of("waitMillis", System.currentTimeMillis() - startTime));
        }
        return new LockResponse(token, failedLocks);
    } finally {
        outstandingLockRequestMultimap.remove(client, request);
        indefinitelyBlockingThreads.remove(Thread.currentThread());
        try {
            for (Entry<ClientAwareReadWriteLock, LockMode> entry : locks.entrySet()) {
                entry.getKey().get(client, entry.getValue()).unlock();
            }
        } catch (Throwable e) {
            // (authorized)
            log.error("Internal lock server error: state has been corrupted!!", UnsafeArg.of("exception", e), SafeArg.of("stacktrace", e.getStackTrace()));
            throw Throwables.throwUncheckedException(e);
        }
    }
}
Also used : ServiceNotAvailableException(com.palantir.common.remoting.ServiceNotAvailableException) LockMode(com.palantir.lock.LockMode) LockDescriptor(com.palantir.lock.LockDescriptor) StringLockDescriptor(com.palantir.lock.StringLockDescriptor) LockResponse(com.palantir.lock.LockResponse) HeldLocksToken(com.palantir.lock.HeldLocksToken) SimpleHeldLocksToken(com.palantir.lock.SimpleHeldLocksToken) LockClient(com.palantir.lock.LockClient) Nullable(javax.annotation.Nullable)

Example 5 with LockMode

use of com.palantir.lock.LockMode in project atlasdb by palantir.

the class LockServiceImpl method unlockInternal.

private <T extends ExpiringToken> boolean unlockInternal(T token, ConcurrentMap<T, HeldLocks<T>> heldLocksMap) {
    @Nullable HeldLocks<T> heldLocks = heldLocksMap.remove(token);
    if (heldLocks == null) {
        return false;
    }
    long heldDuration = System.currentTimeMillis() - token.getCreationDateMs();
    if (requestLogger.isDebugEnabled()) {
        requestLogger.debug("Releasing locks {} after holding for {} ms", UnsafeArg.of("heldLocks", heldLocks), SafeArg.of("heldDuration", heldDuration));
    }
    @Nullable LockClient client = heldLocks.realToken.getClient();
    if (client == null) {
        client = INTERNAL_LOCK_GRANT_CLIENT;
    } else {
        lockClientMultimap.remove(client, token);
    }
    for (Entry<? extends ClientAwareReadWriteLock, LockMode> entry : heldLocks.locks.entries()) {
        entry.getKey().get(client, entry.getValue()).unlock();
    }
    if (heldLocks.realToken.getVersionId() != null) {
        versionIdMap.remove(client, heldLocks.realToken.getVersionId());
    }
    return true;
}
Also used : BLOCK_UNTIL_TIMEOUT(com.palantir.lock.BlockingMode.BLOCK_UNTIL_TIMEOUT) INTERNAL_LOCK_GRANT_CLIENT(com.palantir.lock.LockClient.INTERNAL_LOCK_GRANT_CLIENT) LockClient(com.palantir.lock.LockClient) LockMode(com.palantir.lock.LockMode) Nullable(javax.annotation.Nullable)

Aggregations

LockMode (com.palantir.lock.LockMode)8 LockDescriptor (com.palantir.lock.LockDescriptor)6 StringLockDescriptor (com.palantir.lock.StringLockDescriptor)4 LockClient (com.palantir.lock.LockClient)3 Nullable (javax.annotation.Nullable)3 ImmutableSortedMap (com.google.common.collect.ImmutableSortedMap)2 AtlasRowLockDescriptor (com.palantir.lock.AtlasRowLockDescriptor)2 HeldLocksToken (com.palantir.lock.HeldLocksToken)2 ObjectMapper (com.fasterxml.jackson.databind.ObjectMapper)1 Cell (com.palantir.atlasdb.keyvalue.api.Cell)1 ServiceNotAvailableException (com.palantir.common.remoting.ServiceNotAvailableException)1 BLOCK_UNTIL_TIMEOUT (com.palantir.lock.BlockingMode.BLOCK_UNTIL_TIMEOUT)1 HeldLocksGrant (com.palantir.lock.HeldLocksGrant)1 INTERNAL_LOCK_GRANT_CLIENT (com.palantir.lock.LockClient.INTERNAL_LOCK_GRANT_CLIENT)1 LockRefreshToken (com.palantir.lock.LockRefreshToken)1 LockRequest (com.palantir.lock.LockRequest)1 LockResponse (com.palantir.lock.LockResponse)1 SimpleHeldLocksToken (com.palantir.lock.SimpleHeldLocksToken)1 SimpleTimeDuration (com.palantir.lock.SimpleTimeDuration)1 TimeDuration (com.palantir.lock.TimeDuration)1