Index: src/java/org/apache/hadoop/hbase/regionserver/HRegion.java =================================================================== --- src/java/org/apache/hadoop/hbase/regionserver/HRegion.java (revision 5295) +++ src/java/org/apache/hadoop/hbase/regionserver/HRegion.java (working copy) @@ -59,10 +59,13 @@ import java.util.Collection; import java.util.List; import java.util.Map; + import java.util.Set; import java.util.NavigableSet; import java.util.TreeMap; import java.util.TreeSet; - import java.util.concurrent.ConcurrentHashMap; + import java.util.HashMap; + import java.util.HashSet; + import java.util.Random; import java.util.concurrent.ConcurrentSkipListMap; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; @@ -120,8 +123,13 @@ // Members ////////////////////////////////////////////////////////////////////////////// - private final Map locksToRows = - new ConcurrentHashMap(); + private final Set locksToRows = + new HashSet(); + private final Map lockIds = + new HashMap(); + private int lockIdGenerator = 1; + static private Random rand = new Random(); + protected final Map stores = new ConcurrentSkipListMap(Bytes.BYTES_RAWCOMPARATOR); @@ -1604,18 +1612,34 @@ if (this.closed.get()) { throw new NotServingRegionException("Region " + this + " closed"); } - Integer key = Bytes.mapKey(row); synchronized (locksToRows) { - while (locksToRows.containsKey(key)) { + while (locksToRows.contains(row)) { try { locksToRows.wait(); } catch (InterruptedException ie) { // Empty } } - locksToRows.put(key, row); + // generate a new lockid. Attempt to insert the new [lockid, row]. + // if this lockid already exists in the map then revert and retry + // We could have first done a lockIds.get, and if it does not exist only + // then do a lockIds.put, but the hope is that the lockIds.put will + // mostly return null the first time itself because there won't be + // too many lockId collisions. + byte [] prev = null; + Integer lockId = null; + do { + lockId = new Integer(lockIdGenerator++); + prev = lockIds.put(lockId, row); + if (prev != null) { + lockIds.put(lockId, prev); // revert old value + lockIdGenerator = rand.nextInt(); // generate new start point + } + } while (prev != null); + + locksToRows.add(row); locksToRows.notifyAll(); - return key; + return lockId; } } finally { splitsAndClosesLock.readLock().unlock(); @@ -1628,7 +1652,7 @@ * @return Row that goes with lockid */ byte [] getRowFromLock(final Integer lockid) { - return locksToRows.get(lockid); + return lockIds.get(lockid); } /** @@ -1637,7 +1661,8 @@ */ void releaseRowLock(final Integer lockid) { synchronized (locksToRows) { - locksToRows.remove(lockid); + byte[] row = lockIds.remove(lockid); + locksToRows.remove(row); locksToRows.notifyAll(); } } @@ -1649,7 +1674,7 @@ */ private boolean isRowLocked(final Integer lockid) { synchronized (locksToRows) { - if(locksToRows.containsKey(lockid)) { + if (lockIds.get(lockid) != null) { return true; } return false;