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

Appy commented on HBASE-18703:
------------------------------

Catching up from the top.
There has already been a lot of discussion, some makes sense, while a lot 
doesn't :). Let me start with the main points.

---- 
bq. HRegion.processRowsWithLocks() implementation, doesn't call coprocessor 
hooks but instead calls RowProcessor hooks at appropriate point in execution. 
Many of these hooks/ methods have same names and are called at similar points 
during the course of execution but they are not related!

That's because RowProcessor is not necessarily doing mutations. It's can be 
doing anything- reading, writing, aggregating, etc.  For eg. if i am storing 
analytics data, I may want to write a RowProcessor which can aggregates large 
amount of data on server itself and just returns the result. There's no need of 
coprocessor hooks for this use case. (yeah yeah....better use something else 
for analytics, but you get the point). It's not necessarily for mutations, it's 
much more generic and powerful. 

bq. HRegion.batchMutate() methods call coprocessor hooks but not row 
RowProcessor hooks.
I think hook is bad word to use here. Yeah both CP and RP have overridable 
function, but that's where similarity ends.
CP hooks are events which are invoked when specific code path is travelled. 
This is a promise we make to third party.
That's why on every put, get, delete, we invoke pre\*/post\* functions.
RowProcessor functions are not events. RowProcessor class is like a task - a 
collection of functions - which is given to HRegion. And at different stages, 
HRegion invokes appropriate function of the processor. The act of running a 
RowProcessor has no *direct* relation to Coprocessors (in specific 
implementations, work done by RP might be related to CP).
So batchMutate(), which has nothing to do with RowProcessor and should not be 
invoking RowProcessor hooks anyways.

bq. The major inconsistency here is, one code path uses coprocessors while 
other uses RowProcessor. There are other minor inconsistencies along those two 
code paths.
It's confusing as hell, sure, but my understanding is that there is no 
inconsistency here. 
One path is mutations, and is supposed to invoke coprocessors.
Other path is very high level, generic, row processing mechanism. And is only 
supposed to invoke right RowProcessors steps at right time.

Since we use the second more generic path for mutateRows(), with the help of 
MultiRowMutationProcessor, it's only correct to invoke appropriate CP hooks 
from inside it, otherwise we'll be violating our CP promises.

bq. Comparing these list of steps for 2 methods, we can see the correlation for 
most hooks except for RowProcessor.process()
I think it's only expected.
batchMutate()  already knows what the mutations are. It's coming into it as a 
param. Easy peesy.
But poor processRowsWithLocks() doesn't know what it was called for, so it 
still has to figure it out, and it does so by asking RP for the mutations. 
Let's be sympathetic.
On a serious note, that's by design.

bq. I am proposing that Coprocessors can be used for customized processing 
instead of RowProcessor. Currently this can be done either with RowProcessors 
by calling Region.processRowsWithLocks() or with coprocessors by calling 
Region.batchMutate(). The intended difference between these 2 APIs is that 
Region.batchMutate() will only perform PUT and DELETE operations and 
Region.processRowsWithLocks() can perform any of GET, PUT, DELETE, 
CheckAndMutate etc operations.

So if RowProcessor is more generic, shouldn't we move to it? Why move to an 
option which is the limited one.

----
Note that in batchMutate(), mutations are not related. The batch is not a 
transaction. Some can fail, some can pass. Whereas in processRowsWithLocks(), 
it's transactional. So even if we merge two code paths, we need to keep two 
kinds of locking .

----
The way i see RowProcessor & processRows() combo is -  it will allow us to 
separate out row operations and pack them neatly in classes (outside of 
HRegion, 8000lines!!), and that too in a way such that it is easy to inject 
back.

I think the better design here would be, improve the RowProcessor to provide 
native support for mutations - locks, invoking cp hooks etc. That way we can 
use it for our internal purpose. Advantages are (explicitly listing them again):
1) lot of code sharing : Code around locking, wal edits, pre/postCP hooks can 
be shared. Move batchMutation() to BatchMutationProcessor, and rename 
MultiRowMutationProcessor to denote that unlike BatchMutationProcessor, it's 
transactional.
2) We can split out all mutations related logic from 8000 lines of HRegion 
class.
3) It'll be a better design to expose for use in CPs.

----
Taking a step back, yes, it's a mess. Unification of two paths would be great!

> Inconsistent behavior for preBatchMutate in doMiniBatchMutate and 
> processRowsWithLocks
> --------------------------------------------------------------------------------------
>
>                 Key: HBASE-18703
>                 URL: https://issues.apache.org/jira/browse/HBASE-18703
>             Project: HBase
>          Issue Type: Bug
>          Components: Coprocessors
>            Reporter: Duo Zhang
>            Assignee: Umesh Agashe
>            Priority: Critical
>             Fix For: 2.0.0-alpha-4
>
>         Attachments: hbase-18703.master.001.patch, 
> hbase-18703.master.002.patch, hbase-18703.master.003.patch, 
> hbase-18703.master.004.patch, hbase-18703.master.005.patch, 
> hbase-18703.master.005.patch, hbase-18703.master.005.patch, 
> hbase-18703.master.006.patch, hbase-18703.master.007.patch
>
>
> In doMiniBatchMutate, the preBatchMutate is called before building WAL, but 
> in processRowsWithLocks, we suggest the RowProcessor implementation to build 
> WAL in process  method, which is ahead of preBatchMutate.
> If a CP modifies the mutations, especially if it removes some cells from the 
> mutations, then the behavior of processRowsWithLocks is broken. The changes 
> applied to memstore and WAL will be different. And there is no way to remove 
> entries from a WALEdit through CP. 



--
This message was sent by Atlassian JIRA
(v6.4.14#64029)

Reply via email to