[ 
https://issues.apache.org/jira/browse/HBASE-11126?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14009866#comment-14009866
 ] 

Andrew Purtell commented on HBASE-11126:
----------------------------------------

Patch is looking good.

{code}
@@ -587,6 +587,25 @@ public interface RegionObserver extends Coprocessor {
   void preDelete(final ObserverContext<RegionCoprocessorEnvironment> c, 
       final Delete delete, final WALEdit edit, final Durability durability)
     throws IOException;
+/**
+ * Called before the client updates the timestamp for delete Columns with 
latest timestamp.
+ * <p>
+ * Call CoprocessorEnvironment#bypass to skip default actions
+ * <p>
+ * Call CoprocessorEnvironment#complete to skip any subsequent chained
+ * coprocessors
+ * @param c the environment provided by the region server
+ * @param mutation - the parent mutation associated with this delete cell
+ * @param cell - The deleteColumn with latest version cell
+ * @param byteNow - timestamp bytes
+ * @param family - family bytes
+ * @param get - the get formed using the current cell's row.
+ * Note that the get does not specify the family and qualifier
+ * @throws IOException
+ */
+  void preGetForDeleteVersion(final 
ObserverContext<RegionCoprocessorEnvironment> c,
+      final Mutation mutation, final Cell cell, final byte[] byteNow, final 
byte[] family,
+      final Get get) throws IOException;
{code}

preGetForDeleteVersion needs a better name. What are you doing with this new 
hook? 

In the Javadoc did you mean "Called before the *server* ... "

{code}
@@ -5064,12 +5090,18 @@ public class HRegion implements HeapSize { // , 
Writable{
       rowLock = getRowLock(row);
       try {
         lock(this.updatesLock.readLock());
-        // wait for all prior MVCC transactions to finish - while we hold the 
row lock
-        // (so that we are guaranteed to see the latest state)
-        mvcc.completeMemstoreInsert(mvcc.beginMemstoreInsert());
-        // now start my own transaction
-        w = mvcc.beginMemstoreInsert();
         try {
+          // wait for all prior MVCC transactions to finish - while we hold 
the row lock
+          // (so that we are guaranteed to see the latest state)
+          mvcc.completeMemstoreInsert(mvcc.beginMemstoreInsert());
+          if (this.coprocessorHost != null) {
+            Result r = this.coprocessorHost.preAppendAfterRowLock(append);
+            if(r!= null) {
+              return r;
+            }
+          }
+          // now start my own transaction
+          w = mvcc.beginMemstoreInsert();
           long now = EnvironmentEdgeManager.currentTimeMillis();
           // Process each family
           for (Map.Entry<byte[], List<Cell>> family : 
append.getFamilyCellMap().entrySet()) {
{code}

Why are you moving completeMemstoreInsert and beginMemstoreInsert into the 
inner try? 

{code}
@@ -5254,12 +5286,18 @@ public class HRegion implements HeapSize { // , 
Writable{
       RowLock rowLock = getRowLock(row);
       try {
         lock(this.updatesLock.readLock());
-        // wait for all prior MVCC transactions to finish - while we hold the 
row lock
-        // (so that we are guaranteed to see the latest state)
-        mvcc.completeMemstoreInsert(mvcc.beginMemstoreInsert());
-        // now start my own transaction
-        w = mvcc.beginMemstoreInsert();
         try {
+          // wait for all prior MVCC transactions to finish - while we hold 
the row lock
+          // (so that we are guaranteed to see the latest state)
+          mvcc.completeMemstoreInsert(mvcc.beginMemstoreInsert());
+          if (this.coprocessorHost != null) {
+            Result r = 
this.coprocessorHost.preIncrementAfterRowLock(increment);
+            if (r != null) {
+              return r;
+            }
+          }
+          // now start my own transaction
+          w = mvcc.beginMemstoreInsert();
           long now = EnvironmentEdgeManager.currentTimeMillis();
           // Process each family
           for (Map.Entry<byte [], List<Cell>> family:
{code}

Ditto.

{code}
diff --git 
hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/RSRpcServices.java
 
hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/RSRpcServices.java
index 2e7b022..e0363b2 100644
--- 
hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/RSRpcServices.java
+++ 
hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/RSRpcServices.java
@@ -1730,7 +1730,7 @@ public class RSRpcServices implements 
HBaseRPCErrorHandler,
             ProtobufUtil.toComparator(condition.getComparator());
           if (region.getCoprocessorHost() != null) {
             processed = region.getCoprocessorHost().preCheckAndPut(
-              row, family, qualifier, compareOp, comparator, put);
+                row, family, qualifier, compareOp, comparator, put);
           }
           if (processed == null) {
             boolean result = region.checkAndMutate(row, family,
@@ -1758,7 +1758,7 @@ public class RSRpcServices implements 
HBaseRPCErrorHandler,
             ProtobufUtil.toComparator(condition.getComparator());
           if (region.getCoprocessorHost() != null) {
             processed = region.getCoprocessorHost().preCheckAndDelete(
-              row, family, qualifier, compareOp, comparator, delete);
+                row, family, qualifier, compareOp, comparator, delete);
           }
           if (processed == null) {
             boolean result = region.checkAndMutate(row, family,
{code}

Whitespace only changes, please remove.


> Add RegionObserver pre hooks that operate under row lock
> --------------------------------------------------------
>
>                 Key: HBASE-11126
>                 URL: https://issues.apache.org/jira/browse/HBASE-11126
>             Project: HBase
>          Issue Type: Improvement
>    Affects Versions: 0.99.0, 0.98.3
>            Reporter: Andrew Purtell
>            Assignee: ramkrishna.s.vasudevan
>         Attachments: HBASE-11126.patch, HBASE-11126_1.patch, 
> HBASE-11126_new_2.patch, HBASE-11126_new_3.patch
>
>
> The coprocessor hooks were placed outside of row locks. This was meant to 
> sidestep performance issues arising from significant work done within hook 
> invocations. However as the security code increases in sophistication we are 
> now running into concurrency issues trying to use them as a result of that 
> early decision. Since the initial introduction of coprocessor upcalls there 
> has been some significant refactoring done around them and concurrency 
> control in core has become more complex. This is potentially an issue for 
> many coprocessor users.
> We should do either:\\
> - Move all existing RegionObserver pre* hooks to execute under row lock.
> - Introduce a new set of RegionObserver pre* hooks that execute under row 
> lock, named to indicate such.
> The second option is less likely to lead to surprises.
> All RegionObserver hook Javadoc should be updated with advice to the 
> coprocessor implementor not to take their own row locks in the hook. If the 
> current thread happens to already have a row lock and they try to take a lock 
> on another row, there is a deadlock risk.
> As always a drawback of adding hooks is the potential for performance impact. 
> We should benchmark the impact and decide if the second option above is a 
> viable choice or if the first option is required.
> Finally, we should introduce a higher level interface for managing the 
> registration of 'user' code for execution from the low level hooks. I filed 
> HBASE-11125 to discuss this further.



--
This message was sent by Atlassian JIRA
(v6.2#6252)

Reply via email to