diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/RSRpcServices.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/RSRpcServices.java index 8d4ea4d..87673fb 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/RSRpcServices.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/RSRpcServices.java @@ -27,16 +27,8 @@ import java.net.BindException; import java.net.InetSocketAddress; import java.net.UnknownHostException; import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.Map.Entry; -import java.util.NavigableMap; -import java.util.Set; -import java.util.TreeSet; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.atomic.AtomicLong; @@ -884,6 +876,14 @@ public class RSRpcServices implements HBaseRPCErrorHandler, long before = EnvironmentEdgeManager.currentTime(); boolean batchContainsPuts = false, batchContainsDelete = false; try { + /** HBASE-17924 + * mutationActionMap is a map to map the relation between mutations and actions + * since mutation array may have been reoredered.In order to return the right + * result or exception to the corresponding actions, We need to know which action + * is the mutation belong to. We can't sort ClientProtos.Action array, since they + * are bonded to cellscanners. + */ + Map mutationActionMap = new HashMap(); int i = 0; for (ClientProtos.Action action: mutations) { MutationProto m = action.getMutation(); @@ -902,11 +902,15 @@ public class RSRpcServices implements HBaseRPCErrorHandler, if (!region.getRegionInfo().isMetaTable()) { regionServer.cacheFlusher.reclaimMemStoreMemory(); } - + // HBASE-17924 + // sort to improve lock efficiency + Arrays.sort(mArray); OperationStatus[] codes = region.batchMutate(mArray, HConstants.NO_NONCE, HConstants.NO_NONCE); for (i = 0; i < codes.length; i++) { - int index = mutations.get(i).getIndex(); + Mutation currentMutation = mArray[i]; + ClientProtos.Action currentAction = mutationActionMap.get(currentMutation); + int index = currentAction.getIndex(); Exception e = null; switch (codes[i].getOperationStatusCode()) { case BAD_FAMILY: @@ -1951,6 +1955,9 @@ public class RSRpcServices implements HBaseRPCErrorHandler, walEntries.add(walEntry); } if(edits!=null && !edits.isEmpty()) { + // HBASE-17924 + // sort to improve lock efficiency + Collections.sort(edits); long replaySeqId = (entry.getKey().hasOrigSequenceNumber()) ? entry.getKey().getOrigSequenceNumber() : entry.getKey().getLogSequenceNumber(); OperationStatus[] result = doReplayBatchOp(region, edits, replaySeqId); diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/wal/WALSplitter.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/wal/WALSplitter.java index 77c2d1c..412d4b7 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/wal/WALSplitter.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/wal/WALSplitter.java @@ -2279,7 +2279,7 @@ public class WALSplitter { } /** A struct used by getMutationsFromWALEntry */ - public static class MutationReplay { + public static class MutationReplay implements Comparable { public MutationReplay(MutationType type, Mutation mutation, long nonceGroup, long nonce) { this.type = type; this.mutation = mutation; @@ -2295,6 +2295,25 @@ public class WALSplitter { public final Mutation mutation; public final long nonceGroup; public final long nonce; + + @Override + public int compareTo(final MutationReplay d) { + return this.mutation.compareTo(d.mutation); + } + + @Override + public boolean equals(Object obj) { + if(!(obj instanceof MutationReplay)) { + return false; + } else { + return this.compareTo((MutationReplay)obj) == 0; + } + } + + @Override + public int hashCode() { + return this.mutation.hashCode(); + } } /**