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:
parent
d5e81859e1
commit
a28c5c7ba8
|
@ -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
|
||||||
|
|
|
@ -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();
|
||||||
|
|
Loading…
Reference in New Issue