/* * INESC-ID, Instituto de Engenharia de Sistemas e Computadores Investigação e Desevolvimento em Lisboa * Copyright 2013 INESC-ID and/or its affiliates and other * contributors as indicated by the @author tags. All rights reserved. * See the copyright.txt in the distribution for a full listing of * individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 3.0 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.infinispan.distribution.wrappers; import org.infinispan.container.entries.CacheEntry; import org.infinispan.context.InvocationContext; import org.infinispan.context.impl.TxInvocationContext; import org.infinispan.stats.TransactionsStatisticsRegistry; import org.infinispan.stats.topK.StreamLibContainer; import org.infinispan.stats.translations.ExposedStatistics.IspnStats; import org.infinispan.transaction.xa.GlobalTransaction; import org.infinispan.util.concurrent.TimeoutException; import org.infinispan.util.concurrent.locks.LockManager; import org.infinispan.util.logging.Log; import org.infinispan.util.logging.LogFactory; import java.util.Collection; /** * @author Mircea Markus <mircea.markus@jboss.com> (C) 2011 Red Hat Inc. * @author Diego Didona <didona@gsd.inesc-id.pt> * @author Pedro Ruivo * @since 5.2 */ public class LockManagerWrapper implements LockManager { private static final Log log = LogFactory.getLog(LockManagerWrapper.class); private final LockManager actual; public LockManagerWrapper(LockManager actual) { this.actual = actual; } private boolean updateContentionStats(Object key, TxInvocationContext tctx){ GlobalTransaction holder = (GlobalTransaction)getOwner(key); if(holder!=null){ GlobalTransaction me = tctx.getGlobalTransaction(); if(holder!=me){ if(holder.isRemote()){ TransactionsStatisticsRegistry.incrementValue(IspnStats.LOCK_CONTENTION_TO_REMOTE); } else { TransactionsStatisticsRegistry.incrementValue(IspnStats.LOCK_CONTENTION_TO_LOCAL); } return true; } } return false; } @Override public boolean lockAndRecord(Object key, InvocationContext ctx, long timeoutMillis) throws InterruptedException { log.tracef("LockManagerWrapper.lockAndRecord"); return actual.lockAndRecord(key, ctx, timeoutMillis); } @Override public boolean shareLockAndRecord(Object key, InvocationContext ctx, long timeoutMillis) throws InterruptedException { log.tracef("LockManagerWrapper.shareLockAndRecord"); return actual.shareLockAndRecord(key, ctx, timeoutMillis); } @Override public void unlock(Collection<Object> lockedKeys, Object lockOwner) { log.tracef("LockManagerWrapper.unlock"); actual.unlock(lockedKeys, lockOwner); } @Override public void unlockAll(InvocationContext ctx) { log.tracef("LockManagerWrapper.unlockAll"); actual.unlockAll(ctx); } @Override public boolean ownsLock(Object key, Object owner) { log.tracef("LockManagerWrapper.ownsLock"); return actual.ownsLock(key, owner); } @Override public boolean isLocked(Object key) { log.tracef("LockManagerWrapper.isExclusiveLocked"); return actual.isLocked(key); } @Override public Object getOwner(Object key) { log.tracef("LockManagerWrapper.getOwner"); return actual.getOwner(key); } @Override public String printLockInfo() { log.tracef("LockManagerWrapper.printLockInfo"); return actual.printLockInfo(); } @Override public boolean possiblyLocked(CacheEntry entry) { log.tracef("LockManagerWrapper.possiblyLocked"); return actual.possiblyLocked(entry); } @Override public int getNumberOfLocksHeld() { log.tracef("LockManagerWrapper.getNumberOfLocksHeld"); return actual.getNumberOfLocksHeld(); } @Override public int getLockId(Object key) { log.tracef("LockManagerWrapper.getLockId"); return actual.getLockId(key); } @Override public boolean acquireLock(InvocationContext ctx, Object key, boolean share) throws InterruptedException, TimeoutException { log.tracef("LockManagerWrapper.acquireLock"); long lockingTime = 0; boolean locked, experiencedContention = false, txScope; if(txScope = ctx.isInTxScope()){ experiencedContention = this.updateContentionStats(key,(TxInvocationContext)ctx); lockingTime = System.nanoTime(); } try{ locked = actual.acquireLock(ctx, key, share); //this returns false if you already have acquired the lock previously } catch(TimeoutException e){ StreamLibContainer.getInstance().addLockInformation(key, experiencedContention, true); throw e; } catch(InterruptedException e){ StreamLibContainer.getInstance().addLockInformation(key, experiencedContention, true); throw e; } StreamLibContainer.getInstance().addLockInformation(key, experiencedContention, false); if(txScope && experiencedContention && locked){ lockingTime = System.nanoTime() - lockingTime; TransactionsStatisticsRegistry.addValue(IspnStats.LOCK_WAITING_TIME,lockingTime); TransactionsStatisticsRegistry.incrementValue(IspnStats.NUM_WAITED_FOR_LOCKS); } if(locked){ TransactionsStatisticsRegistry.addTakenLock(key); //Idempotent } return locked; } @Override public boolean acquireLock(InvocationContext ctx, Object key, long timeoutMillis, boolean share) throws InterruptedException, TimeoutException { log.tracef("LockManagerWrapper.acquireLock"); return actual.acquireLock(ctx, key, timeoutMillis, share); } @Override public boolean acquireLockNoCheck(InvocationContext ctx, Object key) throws InterruptedException, TimeoutException { log.tracef("LockManagerWrapper.acquireLockNoCheck"); return actual.acquireLockNoCheck(ctx, key); } }