public boolean releaseLock()

in src/main/java/com/amazonaws/services/dynamodbv2/AmazonDynamoDBLockClient.java [824:915]


    public boolean releaseLock(final ReleaseLockOptions options) {
        Objects.requireNonNull(options, "ReleaseLockOptions cannot be null");

        final LockItem lockItem = options.getLockItem();
        final boolean deleteLock = options.isDeleteLock();
        final boolean bestEffort = options.isBestEffort();
        final Optional<ByteBuffer> data = options.getData();
        Objects.requireNonNull(lockItem, "Cannot release null lockItem");
        if (!lockItem.getOwnerName().equals(this.ownerName)) {
            return false;
        }

        synchronized (lockItem) {
            try {
                // Always remove the heartbeat for the lock. The
                // caller's intention is to release the lock. Stopping the
                // heartbeat alone will do that regardless of whether the Dynamo
                // write succeeds or fails.
                this.locks.remove(lockItem.getUniqueIdentifier());

                //set up expression stuff for DeleteItem or UpdateItem
                //basically any changes require:
                //1. I own the lock
                //2. I know the current version number
                //3. The lock already exists (UpdateItem API can cause a new item to be created if you do not condition the primary keys with attribute_exists)
                final String conditionalExpression;
                final Map<String, AttributeValue> expressionAttributeValues = new HashMap<>();
                expressionAttributeValues.put(RVN_VALUE_EXPRESSION_VARIABLE, AttributeValue.builder().s(lockItem.getRecordVersionNumber()).build());
                expressionAttributeValues.put(OWNER_NAME_VALUE_EXPRESSION_VARIABLE, AttributeValue.builder().s(lockItem.getOwnerName()).build());
                final Map<String, String> expressionAttributeNames = new HashMap<>();
                expressionAttributeNames.put(PK_PATH_EXPRESSION_VARIABLE, partitionKeyName);
                expressionAttributeNames.put(OWNER_NAME_PATH_EXPRESSION_VARIABLE, OWNER_NAME);
                expressionAttributeNames.put(RVN_PATH_EXPRESSION_VARIABLE, RECORD_VERSION_NUMBER);
                if (this.sortKeyName.isPresent()) {
                    conditionalExpression = PK_EXISTS_AND_SK_EXISTS_AND_OWNER_NAME_SAME_AND_RVN_SAME_CONDITION;
                    expressionAttributeNames.put(SK_PATH_EXPRESSION_VARIABLE, sortKeyName.get());
                } else {
                    conditionalExpression = PK_EXISTS_AND_OWNER_NAME_SAME_AND_RVN_SAME_CONDITION;
                }

                final Map<String, AttributeValue> key = getItemKeys(lockItem);
                if (deleteLock) {
                    final DeleteItemRequest deleteItemRequest = DeleteItemRequest.builder()
                            .tableName(tableName)
                            .key(key)
                            .conditionExpression(conditionalExpression)
                            .expressionAttributeNames(expressionAttributeNames)
                            .expressionAttributeValues(expressionAttributeValues)
                            .build();

                    this.dynamoDB.deleteItem(deleteItemRequest);
                } else {
                    final String updateExpression;
                    expressionAttributeNames.put(IS_RELEASED_PATH_EXPRESSION_VARIABLE, IS_RELEASED);
                    expressionAttributeValues.put(IS_RELEASED_VALUE_EXPRESSION_VARIABLE, IS_RELEASED_ATTRIBUTE_VALUE);
                    if (data.isPresent()) {
                        updateExpression = UPDATE_IS_RELEASED_AND_DATA;
                        expressionAttributeNames.put(DATA_PATH_EXPRESSION_VARIABLE, DATA);
                        expressionAttributeValues.put(DATA_VALUE_EXPRESSION_VARIABLE, AttributeValue.builder().b(SdkBytes.fromByteBuffer(data.get())).build());
                    } else {
                        updateExpression = UPDATE_IS_RELEASED;
                    }
                    final UpdateItemRequest updateItemRequest = UpdateItemRequest.builder()
                            .tableName(this.tableName)
                            .key(key)
                            .updateExpression(updateExpression)
                            .conditionExpression(conditionalExpression)
                            .expressionAttributeNames(expressionAttributeNames)
                            .expressionAttributeValues(expressionAttributeValues).build();

                    this.dynamoDB.updateItem(updateItemRequest);
                }
            } catch (final ConditionalCheckFailedException conditionalCheckFailedException) {
                logger.debug("Someone else acquired the lock before you asked to release it", conditionalCheckFailedException);
                return false;
            } catch (final SdkClientException sdkClientException) {
                if (bestEffort) {
                    logger.warn("Ignore SdkClientException and continue to clean up", sdkClientException);
                } else {
                    throw sdkClientException;
                }
            }

            // Only remove the session monitor if no exception thrown above.
            // While moving the heartbeat removal before the DynamoDB call
            // should not cause existing clients problems, there
            // may be existing clients that depend on the monitor firing if they
            // get exceptions from this method.
            this.removeKillSessionMonitor(lockItem.getUniqueIdentifier());
        }
        return true;
    }