HBASE-2985 HRegionServer.multi() no longer calls HRegion.put(List) when possible

git-svn-id: https://svn.apache.org/repos/asf/hbase/trunk@1024074 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Ryan Rawson 2010-10-19 01:01:52 +00:00
parent 113d533ad7
commit 1eede65ae1
6 changed files with 81 additions and 47 deletions

View File

@ -596,6 +596,8 @@ Release 0.21.0 - Unreleased
HBASE-3121 [rest] Do not perform cache control when returning results HBASE-3121 [rest] Do not perform cache control when returning results
HBASE-2669 HCM.shutdownHook causes data loss with HBASE-2669 HCM.shutdownHook causes data loss with
hbase.client.write.buffer != 0 hbase.client.write.buffer != 0
HBASE-2985 HRegionServer.multi() no longer calls HRegion.put(List) when
possible
IMPROVEMENTS IMPROVEMENTS
HBASE-1760 Cleanup TODOs in HTable HBASE-1760 Cleanup TODOs in HTable

View File

@ -1176,7 +1176,7 @@ public class HConnectionManager {
List<Pair<Integer, Result>> regionResults = e.getValue(); List<Pair<Integer, Result>> regionResults = e.getValue();
for (Pair<Integer, Result> regionResult : regionResults) { for (Pair<Integer, Result> regionResult : regionResults) {
if (regionResult == null) { if (regionResult == null) {
// failed // if the first/only record is 'null' the entire region failed.
LOG.debug("Failures for region: " + Bytes.toStringBinary(regionName) + ", removing from cache"); LOG.debug("Failures for region: " + Bytes.toStringBinary(regionName) + ", removing from cache");
} else { } else {
// success // success

View File

@ -551,7 +551,10 @@ public class HTable implements HTableInterface {
} }
/** /**
* Method that does a batch call on Deletes, Gets and Puts. * Method that does a batch call on Deletes, Gets and Puts. The ordering of
* execution of the actions is not defined. Meaning if you do a Put and a
* Get in the same {@link #batch} call, you will not necessarily be
* guaranteed that the Get returns what the Put had put.
* *
* @param actions list of Get, Put, Delete objects * @param actions list of Get, Put, Delete objects
* @param results Empty Result[], same size as actions. Provides access to partial * @param results Empty Result[], same size as actions. Provides access to partial

View File

@ -42,8 +42,8 @@ public class MultiResponse implements Writable {
// map of regionName to list of (Results paired to the original index for that // map of regionName to list of (Results paired to the original index for that
// Result) // Result)
private Map<byte[], List<Pair<Integer, Result>>> results = new TreeMap<byte[], List<Pair<Integer, Result>>>( private Map<byte[], List<Pair<Integer, Result>>> results =
Bytes.BYTES_COMPARATOR); new TreeMap<byte[], List<Pair<Integer, Result>>>(Bytes.BYTES_COMPARATOR);
public MultiResponse() { public MultiResponse() {
} }

View File

@ -2330,9 +2330,11 @@ public class HRegionServer implements HRegionInterface, HBaseRPCErrorHandler,
// actions in the list. // actions in the list.
Collections.sort(actionsForRegion); Collections.sort(actionsForRegion);
Row action = null; Row action = null;
List<Action> puts = new ArrayList<Action>();
try { try {
for (Action a : actionsForRegion) { for (Action a : actionsForRegion) {
action = a.getAction(); action = a.getAction();
// TODO catch exceptions so we can report them on a per-item basis.
if (action instanceof Delete) { if (action instanceof Delete) {
delete(regionName, (Delete) action); delete(regionName, (Delete) action);
response.add(regionName, new Pair<Integer, Result>( response.add(regionName, new Pair<Integer, Result>(
@ -2341,14 +2343,50 @@ public class HRegionServer implements HRegionInterface, HBaseRPCErrorHandler,
response.add(regionName, new Pair<Integer, Result>( response.add(regionName, new Pair<Integer, Result>(
a.getOriginalIndex(), get(regionName, (Get) action))); a.getOriginalIndex(), get(regionName, (Get) action)));
} else if (action instanceof Put) { } else if (action instanceof Put) {
put(regionName, (Put) action); puts.add(a);
response.add(regionName, new Pair<Integer, Result>(
a.getOriginalIndex(), new Result()));
} else { } else {
LOG.debug("Error: invalid Action, row must be a Get, Delete or Put."); LOG.debug("Error: invalid Action, row must be a Get, Delete or Put.");
throw new IllegalArgumentException("Invalid Action, row must be a Get, Delete or Put."); throw new IllegalArgumentException("Invalid Action, row must be a Get, Delete or Put.");
} }
} }
// We do the puts with result.put so we can get the batching efficiency
// we so need. All this data munging doesn't seem great, but at least
// we arent copying bytes or anything.
if (!puts.isEmpty()) {
HRegion region = getRegion(regionName);
if (!region.getRegionInfo().isMetaTable()) {
this.cacheFlusher.reclaimMemStoreMemory();
}
Pair<Put,Integer> [] putsWithLocks = new Pair[puts.size()];
int i = 0;
for (Action a : puts) {
Put p = (Put) a.getAction();
Integer lock = getLockFromId(p.getLockId());
putsWithLocks[i++] = new Pair<Put, Integer>(p, lock);
}
this.requestCount.addAndGet(puts.size());
OperationStatusCode[] codes = region.put(putsWithLocks);
for( i = 0 ; i < codes.length ; i++) {
OperationStatusCode code = codes[i];
Action theAction = puts.get(i);
Result result = null;
if (code == OperationStatusCode.SUCCESS) {
result = new Result();
}
// TODO turning the alternate exception into a different result
response.add(regionName,
new Pair<Integer, Result>(
theAction.getOriginalIndex(), result));
}
}
} catch (IOException ioe) { } catch (IOException ioe) {
if (multi.size() == 1) throw ioe; if (multi.size() == 1) throw ioe;
LOG.debug("Exception processing " + LOG.debug("Exception processing " +

View File

@ -354,17 +354,11 @@ public class TestMultiParallel {
get.addColumn(BYTES_FAMILY, QUALIFIER); get.addColumn(BYTES_FAMILY, QUALIFIER);
actions.add(get); actions.add(get);
// 5 get of the put in #2 (entire family) // There used to be a 'get' of a previous put here, but removed
get = new Get(KEYS[10]); // since this API really cannot guarantee order in terms of mixed
get.addFamily(BYTES_FAMILY); // get/puts.
actions.add(get);
// 6 get of the delete from #3 // 5 put of new column
get = new Get(KEYS[20]);
get.addColumn(BYTES_FAMILY, QUALIFIER);
actions.add(get);
// 7 put of new column
put = new Put(KEYS[40]); put = new Put(KEYS[40]);
put.add(BYTES_FAMILY, qual2, val2); put.add(BYTES_FAMILY, qual2, val2);
actions.add(put); actions.add(put);
@ -378,10 +372,7 @@ public class TestMultiParallel {
validateEmpty(results[2]); validateEmpty(results[2]);
validateEmpty(results[3]); validateEmpty(results[3]);
validateResult(results[4]); validateResult(results[4]);
validateResult(results[5]); validateEmpty(results[5]);
validateResult(results[5], qual2, val2); // testing second column in #5
validateEmpty(results[6]); // deleted
validateEmpty(results[7]);
// validate last put, externally from the batch // validate last put, externally from the batch
get = new Get(KEYS[40]); get = new Get(KEYS[40]);