All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.palantir.lock.LockResponse Maven / Gradle / Ivy

/*
 * (c) Copyright 2018 Palantir Technologies Inc. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.palantir.lock;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.google.common.collect.ImmutableSortedMap;
import com.palantir.logsafe.Preconditions;
import com.palantir.logsafe.Unsafe;
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;

/**
 * Represents the result of calling {@link LockService#lockWithFullLockResponse(LockClient, LockRequest)} on
 * the lock server. If locks were successfully acquired, then {@link #success()}
 * returns true and {@link #getToken()} returns the token which
 * represents the held locks.
 *
 * @author jtamer
 */
@JsonDeserialize(builder = LockResponse.SerializationProxy.class)
@Immutable
public final class LockResponse implements Serializable {
    private static final long serialVersionUID = 0xd67972b13e30eff7L;

    @Nullable
    private final HeldLocksToken token;

    private final boolean isBlockAndRelease;
    private final ImmutableSortedMap lockHolders;

    public LockResponse(@Nullable HeldLocksToken token) {
        this(token, ImmutableSortedMap.of());
    }

    /**
     * This should only get created by the Lock Service.
     */
    public LockResponse(@Nullable HeldLocksToken token, Map lockHolders) {
        this.token = token;
        this.lockHolders = ImmutableSortedMap.copyOf(lockHolders);
        isBlockAndRelease = false;
        Preconditions.checkArgument(token != null || !this.lockHolders.isEmpty());
    }

    /**
     * This should only get created by the Lock Service.
     * 

* This constructor is for {@link BlockingMode#BLOCK_INDEFINITELY_THEN_RELEASE} */ @SuppressWarnings("BadAssert") // performance sensitive asserts public LockResponse(Map lockHolders) { this.token = null; this.lockHolders = ImmutableSortedMap.copyOf(lockHolders); assert this.lockHolders.isEmpty(); isBlockAndRelease = true; } /** * Creates a new, successful {@code LockResponse} wrapping the given token, * with an empty lock holders map. */ public static LockResponse createSuccessful(HeldLocksToken token) { return new LockResponse(Preconditions.checkNotNull(token), ImmutableSortedMap.of()); } /** * Returns true if locks were acquired. Note that if the lock * request specified {@link BlockingMode#BLOCK_INDEFINITELY} (the default * behavior) or {@link BlockingMode#BLOCK_INDEFINITELY_THEN_RELEASE}, * then this method is guaranteed to return true. */ public boolean success() { if (isBlockAndRelease) { return lockHolders.isEmpty(); } return token != null; } /** * If {@link #success()} is true, then this method returns a token * representing the held locks; otherwise, this method returns null. */ @Nullable public HeldLocksToken getToken() { return token; } @JsonIgnore @Nullable public LockRefreshToken getLockRefreshToken() { return token == null ? null : token.getLockRefreshToken(); } public boolean isBlockAndRelease() { return isBlockAndRelease; } public List getLocks() { return lockHolders.entrySet().stream() .map(input -> ImmutableLockWithClient.builder() .lockDescriptor(input.getKey()) .lockClient(input.getValue()) .build()) .collect(Collectors.toList()); } /** * Returns a map of lock descriptors and lock clients. Each entry's key is a * lock which could not be acquired by the lock server, and its value is one * of the clients who was already holding the lock. If multiple clients are * holding a read lock, then one of those clients is picked arbitrarily to * be used as the value in this map. *

* Note that this map will not necessarily contain every lock which could * not be acquired; however, if at least one of the requested locks was not * acquired, then this map is guaranteed to contain at least one entry. Also * note that even if {@link #success()} returns true, this map might * not be empty if the lock request specified * {@link LockGroupBehavior#LOCK_AS_MANY_AS_POSSIBLE}. */ @JsonIgnore public ImmutableSortedMap getLockHolders() { return lockHolders; } @Override public boolean equals(@Nullable Object obj) { if (this == obj) { return true; } if (!(obj instanceof LockResponse)) { return false; } LockResponse that = (LockResponse) obj; return Objects.equals(token, that.token) && lockHolders.equals(that.getLockHolders()) && isBlockAndRelease == that.isBlockAndRelease(); } @Override public int hashCode() { return Objects.hash(token, lockHolders, isBlockAndRelease); } @Unsafe public String toString(long currentTimeMillis) { return "LockResponse{" // + "token=" + ((token == null) ? "null" : token.toString(currentTimeMillis)) // + ", lockHolders=" + lockHolders // + ", isBlockAndRelease=" + isBlockAndRelease // + "'}"; } private void readObject(@SuppressWarnings("unused") ObjectInputStream in) throws InvalidObjectException { throw new InvalidObjectException("proxy required"); } private Object writeReplace() { return new SerializationProxy(this); } static class SerializationProxy implements Serializable { private static final long serialVersionUID = 0xcff22b33b08dd857L; @Nullable private final HeldLocksToken token; private final ImmutableSortedMap lockHolders; private final boolean isBlockAndRelease; SerializationProxy(LockResponse lockResponse) { this.token = lockResponse.token; this.lockHolders = lockResponse.lockHolders; this.isBlockAndRelease = lockResponse.isBlockAndRelease; } @JsonCreator SerializationProxy( @JsonProperty("token") HeldLocksToken token, @JsonProperty("locks") List lockWithClients, @JsonProperty("blockAndRelease") boolean isBlockAndRelease) { if (lockWithClients == null) { lockHolders = ImmutableSortedMap.of(); } else { ImmutableSortedMap.Builder lockHoldersBuilder = ImmutableSortedMap.naturalOrder(); for (LockWithClient lock : lockWithClients) { lockHoldersBuilder.put(lock.getLockDescriptor(), lock.getLockClient()); } this.lockHolders = lockHoldersBuilder.buildOrThrow(); } this.token = token; this.isBlockAndRelease = isBlockAndRelease; } public LockResponse build() { return (LockResponse) readResolve(); } Object readResolve() { if (isBlockAndRelease) { return new LockResponse(lockHolders); } return new LockResponse(token, lockHolders); } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy