package org.infinispan.stats.wrappers;
import java.util.Collection;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import org.infinispan.context.InvocationContext;
import org.infinispan.stats.topK.StreamSummaryContainer;
import org.infinispan.util.concurrent.locks.KeyAwareLockPromise;
import org.infinispan.util.concurrent.locks.LockManager;
import org.infinispan.util.concurrent.locks.LockState;
import org.infinispan.util.concurrent.locks.impl.InfinispanLock;
/**
* Top-key stats about locks.
*
* @author Pedro Ruivo
* @since 6.0
*/
public class TopKeyLockManager implements LockManager {
private final LockManager current;
private final StreamSummaryContainer container;
public TopKeyLockManager(LockManager current, StreamSummaryContainer container) {
this.current = current;
this.container = container;
}
@Override
public KeyAwareLockPromise lock(Object key, Object lockOwner, long time, TimeUnit unit) {
if (lockOwnerAlreadyExists(key, lockOwner)) {
return current.lock(key, lockOwner, time, unit);
}
KeyAwareLockPromise lockPromise = current.lock(key, lockOwner, time, unit);
final boolean contented = !lockOwner.equals(current.getOwner(key));
lockPromise.addListener(state -> container.addLockInformation(key, contented, state != LockState.ACQUIRED));
return lockPromise;
}
@Override
public KeyAwareLockPromise lockAll(Collection<?> keys, Object lockOwner, long time, TimeUnit unit) {
final Set<Object> keysToTrack = keys.stream().filter(key -> !lockOwnerAlreadyExists(key, lockOwner)).collect(Collectors.toSet());
final KeyAwareLockPromise lockPromise = current.lockAll(keys, lockOwner, time, unit);
final Set<Object> contentedKeys = keys.stream().filter(key -> !lockOwner.equals(current.getOwner(key))).collect(Collectors.toSet());
lockPromise.addListener((lockedKey, state) -> {
if (keysToTrack.contains(lockedKey)) {
container.addLockInformation(lockedKey, contentedKeys.contains(lockedKey), state != LockState.ACQUIRED);
}
});
return lockPromise;
}
@Override
public void unlock(Object key, Object lockOwner) {
current.unlock(key, lockOwner);
}
@Override
public void unlockAll(Collection<?> keys, Object lockOwner) {
current.unlockAll(keys, lockOwner);
}
@Override
public void unlockAll(InvocationContext ctx) {
current.unlockAll(ctx);
}
@Override
public boolean ownsLock(Object key, Object owner) {
return current.ownsLock(key, owner);
}
@Override
public boolean isLocked(Object key) {
return current.isLocked(key);
}
@Override
public Object getOwner(Object key) {
return current.getOwner(key);
}
@Override
public String printLockInfo() {
return current.printLockInfo();
}
@Override
public int getNumberOfLocksHeld() {
return current.getNumberOfLocksHeld();
}
@Override
public InfinispanLock getLock(Object key) {
return current.getLock(key);
}
private boolean lockOwnerAlreadyExists(Object key, Object lockOwner) {
final InfinispanLock lock = current.getLock(key);
return lock != null && lock.containsLockOwner(lockOwner);
}
}