HBASE-952 Deadlock in HRegion.batchUpdate

git-svn-id: https://svn.apache.org/repos/asf/hadoop/hbase/trunk@707457 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Jim Kellerman 2008-10-23 19:43:56 +00:00
parent d5e81859e1
commit a28c5c7ba8
2 changed files with 70 additions and 70 deletions

View File

@ -40,6 +40,7 @@ Release 0.19.0 - Unreleased
HBASE-946 Row with 55k deletes timesout scanner lease HBASE-946 Row with 55k deletes timesout scanner lease
HBASE-950 HTable.commit no longer works with existing RowLocks though it's still in API HBASE-950 HTable.commit no longer works with existing RowLocks though it's still in API
HBASE-728 Support for HLog appends HBASE-728 Support for HLog appends
HBASE-952 Deadlock in HRegion.batchUpdate
IMPROVEMENTS IMPROVEMENTS
HBASE-901 Add a limit to key length, check key and value length on client side HBASE-901 Add a limit to key length, check key and value length on client side

View File

@ -1125,21 +1125,17 @@ public class HRegion implements HConstants {
* *
* @param row * @param row
* @param column * @param column
* @param timestamp * @param ts
* @param numVersions * @param nv
* @return array of values one element per version that matches the timestamp, * @return array of values one element per version that matches the timestamp,
* or null if there are no matches. * or null if there are no matches.
* @throws IOException * @throws IOException
*/ */
public Cell[] get(byte [] row, byte [] column, long timestamp, public Cell[] get(final byte[] row, final byte[] column, final long ts,
int numVersions) final int nv)
throws IOException { throws IOException {
if (timestamp == -1) { long timestamp = ts == -1 ? HConstants.LATEST_TIMESTAMP : ts;
timestamp = Long.MAX_VALUE; int numVersions = nv == -1 ? 1 : nv;
}
if (numVersions == -1) {
numVersions = 1;
}
splitsAndClosesLock.readLock().lock(); splitsAndClosesLock.readLock().lock();
try { try {
@ -1354,19 +1350,14 @@ public class HRegion implements HConstants {
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
/** /**
* Batch update many rows and take splitsAndClosesLock so we don't get * Batch update many rows
* blocked while updating.
* @param bus * @param bus
* @param locks
* @throws IOException
*/ */
public void batchUpdate(BatchUpdate[] bus, Integer[] locks) public void batchUpdate(BatchUpdate[] bus, Integer[] locks) throws IOException {
throws IOException { for (int i = 0; i < bus.length; i++) {
splitsAndClosesLock.readLock().lock(); batchUpdate(bus[i], locks[i]);
try {
for (int i = 0; i < bus.length; i++) {
batchUpdate(bus[i], locks[i]);
}
} finally {
splitsAndClosesLock.readLock().unlock();
} }
} }
@ -1413,60 +1404,65 @@ public class HRegion implements HConstants {
// will be extremely rare; we'll deal with it when it happens. // will be extremely rare; we'll deal with it when it happens.
checkResources(); checkResources();
// We obtain a per-row lock, so other clients will block while one client splitsAndClosesLock.readLock().lock();
// performs an update. The read lock is released by the client calling
// #commit or #abort or if the HRegionServer lease on the lock expires.
// See HRegionServer#RegionListener for how the expire on HRegionServer
// invokes a HRegion#abort.
byte [] row = b.getRow();
// If we did not pass an existing row lock, obtain a new one
Integer lid = getLock(lockid,row);
long commitTime = (b.getTimestamp() == LATEST_TIMESTAMP) ?
System.currentTimeMillis() : b.getTimestamp();
try { try {
List<byte []> deletes = null; // We obtain a per-row lock, so other clients will block while one client
for (BatchOperation op: b) { // performs an update. The read lock is released by the client calling
HStoreKey key = new HStoreKey(row, op.getColumn(), commitTime, // #commit or #abort or if the HRegionServer lease on the lock expires.
this.regionInfo); // See HRegionServer#RegionListener for how the expire on HRegionServer
byte[] val = null; // invokes a HRegion#abort.
if (op.isPut()) { byte [] row = b.getRow();
val = op.getValue(); // If we did not pass an existing row lock, obtain a new one
if (HLogEdit.isDeleted(val)) { Integer lid = getLock(lockid,row);
throw new IOException("Cannot insert value: " + val); long commitTime = (b.getTimestamp() == LATEST_TIMESTAMP) ?
} System.currentTimeMillis() : b.getTimestamp();
} else { try {
if (b.getTimestamp() == LATEST_TIMESTAMP) { List<byte []> deletes = null;
// Save off these deletes for (BatchOperation op: b) {
if (deletes == null) { HStoreKey key = new HStoreKey(row, op.getColumn(), commitTime,
deletes = new ArrayList<byte []>(); this.regionInfo);
byte[] val = null;
if (op.isPut()) {
val = op.getValue();
if (HLogEdit.isDeleted(val)) {
throw new IOException("Cannot insert value: " + val);
} }
deletes.add(op.getColumn());
} else { } else {
val = HLogEdit.deleteBytes.get(); if (b.getTimestamp() == LATEST_TIMESTAMP) {
// Save off these deletes
if (deletes == null) {
deletes = new ArrayList<byte []>();
}
deletes.add(op.getColumn());
} else {
val = HLogEdit.deleteBytes.get();
}
}
if (val != null) {
localput(lid, key, val);
} }
} }
if (val != null) { TreeMap<HStoreKey, byte[]> edits =
localput(lid, key, val); this.targetColumns.remove(lid);
}
}
TreeMap<HStoreKey, byte[]> edits =
this.targetColumns.remove(lid);
if (edits != null && edits.size() > 0) { if (edits != null && edits.size() > 0) {
update(edits, writeToWAL); update(edits, writeToWAL);
}
if (deletes != null && deletes.size() > 0) {
// We have some LATEST_TIMESTAMP deletes to run.
for (byte [] column: deletes) {
deleteMultiple(row, column, LATEST_TIMESTAMP, 1);
} }
if (deletes != null && deletes.size() > 0) {
// We have some LATEST_TIMESTAMP deletes to run.
for (byte [] column: deletes) {
deleteMultiple(row, column, LATEST_TIMESTAMP, 1);
}
}
} catch (IOException e) {
this.targetColumns.remove(Long.valueOf(lid));
throw e;
} finally {
if(lockid == null) releaseRowLock(lid);
} }
} catch (IOException e) {
this.targetColumns.remove(Long.valueOf(lid));
throw e;
} finally { } finally {
if(lockid == null) releaseRowLock(lid); splitsAndClosesLock.readLock().unlock();
} }
} }
@ -1539,8 +1535,8 @@ public class HRegion implements HConstants {
* @param lockid Row lock * @param lockid Row lock
* @throws IOException * @throws IOException
*/ */
public void deleteAll(final byte [] row, final long ts, @SuppressWarnings("unchecked")
final Integer lockid) public void deleteAll(final byte [] row, final long ts, final Integer lockid)
throws IOException { throws IOException {
checkReadOnly(); checkReadOnly();
Integer lid = getLock(lockid, row); Integer lid = getLock(lockid, row);
@ -1571,6 +1567,7 @@ public class HRegion implements HConstants {
* @param lockid Row lock * @param lockid Row lock
* @throws IOException * @throws IOException
*/ */
@SuppressWarnings("unchecked")
public void deleteFamily(byte [] row, byte [] family, long timestamp, public void deleteFamily(byte [] row, byte [] family, long timestamp,
final Integer lockid) final Integer lockid)
throws IOException{ throws IOException{
@ -1606,6 +1603,7 @@ public class HRegion implements HConstants {
* {@link HConstants#ALL_VERSIONS} to delete all. * {@link HConstants#ALL_VERSIONS} to delete all.
* @throws IOException * @throws IOException
*/ */
@SuppressWarnings("unchecked")
private void deleteMultiple(final byte [] row, final byte [] column, private void deleteMultiple(final byte [] row, final byte [] column,
final long ts, final int versions) final long ts, final int versions)
throws IOException { throws IOException {
@ -1643,6 +1641,7 @@ public class HRegion implements HConstants {
* @param val Value to enter into cell * @param val Value to enter into cell
* @throws IOException * @throws IOException
*/ */
@SuppressWarnings("unchecked")
private void localput(final Integer lockid, final HStoreKey key, private void localput(final Integer lockid, final HStoreKey key,
final byte [] val) final byte [] val)
throws IOException { throws IOException {
@ -1870,9 +1869,8 @@ public class HRegion implements HConstants {
synchronized (locksToRows) { synchronized (locksToRows) {
if(locksToRows.containsKey(lockid)) { if(locksToRows.containsKey(lockid)) {
return true; return true;
} else {
return false;
} }
return false;
} }
} }
@ -2219,6 +2217,7 @@ public class HRegion implements HConstants {
* *
* @throws IOException * @throws IOException
*/ */
@SuppressWarnings("unchecked")
public static void addRegionToMETA(HRegion meta, HRegion r) public static void addRegionToMETA(HRegion meta, HRegion r)
throws IOException { throws IOException {
meta.checkResources(); meta.checkResources();