Clover coverage report -
Coverage timestamp: Sun Nov 1 2009 23:08:24 UTC
file stats: LOC: 190   Methods: 9
NCLOC: 112   Classes: 2
 
 Source file Conditionals Statements Methods TOTAL
LockManager.java 50% 71.9% 55.6% 65.1%
coverage coverage
 1    /*
 2    * Licensed to the Apache Software Foundation (ASF) under one or more
 3    * contributor license agreements. See the NOTICE file distributed with
 4    * this work for additional information regarding copyright ownership.
 5    * The ASF licenses this file to You under the Apache License, Version 2.0
 6    * (the "License"); you may not use this file except in compliance with
 7    * the License. You may obtain a copy of the License at
 8    *
 9    * http://www.apache.org/licenses/LICENSE-2.0
 10    *
 11    * Unless required by applicable law or agreed to in writing, software
 12    * distributed under the License is distributed on an "AS IS" BASIS,
 13    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14    * See the License for the specific language governing permissions and
 15    * limitations under the License.
 16    *
 17    * $Id: LockManager.java 541508 2007-05-25 01:54:12Z vgritsenko $
 18    */
 19   
 20    package org.apache.xindice.util;
 21   
 22    import java.util.HashMap;
 23    import java.util.Map;
 24   
 25    import org.apache.commons.logging.Log;
 26    import org.apache.commons.logging.LogFactory;
 27   
 28    /**
 29    * LockManager manages resource locks. A resource is any shared object that
 30    * can be represented as a long. The LockManager should be constructed using
 31    * the maximum number of concurrent clients a specific resource might have.
 32    *
 33    * @version $Revision: 541508 $, $Date: 2007-05-24 18:54:12 -0700 (Thu, 24 May 2007) $
 34    */
 35    public final class LockManager {
 36   
 37    private static final Log log = LogFactory.getLog(LockManager.class);
 38   
 39    private int maxLocks = 0;
 40    private Map locks = new HashMap(); // Long to LockInfo
 41   
 42  19 public LockManager(int maxLocks) {
 43  19 this.maxLocks = maxLocks;
 44    }
 45   
 46    /**
 47    * acquireSharedLock acquires a shared lock on a resource. Shared locks
 48    * are typically used for reads.
 49    */
 50  0 public void acquireSharedLock(long id) {
 51  0 acquireSharedLock(new Long(id));
 52    }
 53   
 54    /**
 55    * acquireSharedLock acquires a shared lock on a resource. Shared locks
 56    * are typically used for reads.
 57    */
 58  1961 public void acquireSharedLock(Object key) {
 59  1961 LockInfo info;
 60  1961 synchronized (this) {
 61  1961 info = (LockInfo) locks.get(key);
 62  1961 if (info == null) {
 63  1961 info = new LockInfo();
 64  1961 locks.put(key, info);
 65    }
 66    }
 67  1961 synchronized (info) {
 68  1961 while (info.count >= maxLocks) {
 69  0 try {
 70  0 info.wait();
 71    } catch (Exception e) {
 72  0 if (log.isWarnEnabled()) {
 73  0 log.warn("ignored exception", e);
 74    }
 75    }
 76    }
 77  1961 info.count++;
 78    }
 79    }
 80   
 81    /**
 82    * releaseSharedLock releases a shared lock on a resource. Shared locks
 83    * are typically used for reads.
 84    */
 85  0 public void releaseSharedLock(long id) {
 86  0 releaseSharedLock(new Long(id));
 87    }
 88   
 89    /**
 90    * releaseSharedLock releases a shared lock on a resource. Shared locks
 91    * are typically used for reads.
 92    */
 93  1961 public void releaseSharedLock(Object key) {
 94  1961 LockInfo info;
 95  1961 synchronized (this) {
 96  1961 info = (LockInfo) locks.get(key);
 97    }
 98  1961 if (info == null) {
 99  0 return;
 100    }
 101   
 102  1961 synchronized (info) {
 103  1961 info.count--;
 104  1961 info.notify();
 105  1961 if (info.count == 0) {
 106  1961 synchronized (this) {
 107  1961 locks.remove(key);
 108    }
 109    }
 110    }
 111    }
 112   
 113    /**
 114    * acquireExclusiveLock acquires an exclusive lock on a resource. Exclusive
 115    * locks are typically used for writes.
 116    */
 117  0 public void acquireExclusiveLock(long id) {
 118  0 acquireExclusiveLock(new Long(id));
 119    }
 120   
 121    /**
 122    * acquireExclusiveLock acquires an exclusive lock on a resource. Exclusive
 123    * locks are typically used for writes.
 124    */
 125  4027 public void acquireExclusiveLock(Object key) {
 126  4026 LockInfo info;
 127  4027 synchronized (this) {
 128  4027 info = (LockInfo) locks.get(key);
 129  4027 if (info == null) {
 130  4008 info = new LockInfo();
 131  4008 locks.put(key, info);
 132    }
 133    }
 134  4027 synchronized (info) {
 135  4027 int total = 0;
 136  4027 int stolen = 0;
 137  4027 while (total < maxLocks && info.count >= maxLocks) {
 138  0 try {
 139  0 info.wait();
 140    } catch (Exception e) {
 141  0 if (log.isWarnEnabled()) {
 142  0 log.warn("ignored exception", e);
 143    }
 144    }
 145  0 stolen = maxLocks - info.count;
 146  0 total += stolen;
 147  0 info.count += stolen;
 148    }
 149    }
 150    }
 151   
 152    /**
 153    * releaseExclusiveLock releases an exclusive lock on a resource. Exclusive
 154    * locks are typically used for writes.
 155    */
 156  0 public void releaseExclusiveLock(long id) {
 157  0 releaseExclusiveLock(new Long(id));
 158    }
 159   
 160    /**
 161    * releaseExclusiveLock releases an exclusive lock on a resource. Exclusive
 162    * locks are typically used for writes.
 163    */
 164  4027 public void releaseExclusiveLock(Object key) {
 165  4027 LockInfo info;
 166  4027 synchronized (this) {
 167  4027 info = (LockInfo) locks.get(key);
 168    }
 169  4027 if (info == null) {
 170  19 return;
 171    }
 172   
 173  4008 synchronized (info) {
 174  4006 info.count = 0;
 175  4008 info.notify();
 176  4008 if (info.count == 0) {
 177  4007 synchronized (this) {
 178  4008 locks.remove(key);
 179    }
 180    }
 181    }
 182    }
 183   
 184    /**
 185    * LockInfo is just an int wrapper.
 186    */
 187    private class LockInfo {
 188    public int count = 0;
 189    }
 190    }