Thanks - I see that the lock is taken internal to checkAndMutate. I'm wondering whether it is a better idea to actually pass in a Constraint (or even Constraints) as the checkAndMutate argument. Right now it is taking in an Comparator and a CompareOp for verification. But, this could just be a special case of Constraint which is evaluated within the lock.
In other words, we could open up a richer Constraint checking api where any "functional" Constraint check can be performed in the checkAndPut operation. This would also not have the same performance impact of taking a rowLock in preCheckAndPut and release in postCheckAndPut. And - it is really (in my mind) implementing the compare-and-set more generically. I also see the potential of passing in multiple constraints (say upper/lower bounds in Increment/Decrement operations) etc. --Suraj On Sat, Dec 3, 2011 at 7:44 PM, Ted Yu <[email protected]> wrote: > From HRegionServer.checkAndPut(): > if (region.getCoprocessorHost() != null) { > Boolean result = region.getCoprocessorHost() > .preCheckAndPut(row, family, qualifier, CompareOp.EQUAL, comparator, > put); > ... > boolean result = checkAndMutate(regionName, row, family, qualifier, > CompareOp.EQUAL, new BinaryComparator(value), put, > lock); > We can see that the lock isn't taken for preCheckAndPut(). > > To satisfy Suraj's requirement, I think a slight change to checkAndPut() is > needed so that atomicity can be achieved across preCheckAndPut() and > checkAndMutate(). > > Cheers > > On Sat, Dec 3, 2011 at 4:54 PM, Suraj Varma <[email protected]> wrote: > >> Just so my question is clear ... everything I'm suggesting is in the >> context of a single row (not cross row / table). - so, yes, I'm >> guessing obtaining a RowLock on the region side during preCheckAndPut >> / postCheckAndPut would certainly work. Which was why I was asking >> whether the pre/postCheckAndPut obtains the row lock or whether the >> row lock is only obtained within checkAndPut. >> >> Let's say the coprocessor takes a rowlock in preCheckAndPut ... will >> that even work? i.e. can the same rowlock be inherited by the >> checkAndPut api within that thread's context? Or will preCheckAndPut >> have to release the lock so that checkAndPut can take it (which won't >> work for my case, as it has to be atomic between the preCheck and >> Put.) >> >> Thanks for pointing me to the Constraints functionality - I'll take a >> look at whether it could potentially work. >> --Suraj >> >> On Sat, Dec 3, 2011 at 10:25 AM, Jesse Yates <[email protected]> >> wrote: >> > I think the feature you are looking for is a Constraint. Currently they >> are >> > being added to 0.94 in >> > HBASE-4605<https://issues.apache.org/jira/browse/HBASE-4605>; >> > they are almost ready to be rolled in, and backporting to 0.92 is >> > definitely doable. >> > >> > However, Constraints aren't going to be quite flexible enough to >> > efficiently support what you are describing. For instance, with a >> > constraint, you are ideally just checking the put value against some >> simple >> > constraint (never over 10 or always an integer), but looking at the >> current >> > state of the table before allowing the put would currently require >> creating >> > a full blown connection to the local table through another HTable. >> > >> > In the short term, you could write a simple coprocessor to do this >> checking >> > and then move over to constraints (which are a simpler, more flexible, >> way >> > of doing this) when the necessary features have been added. >> > >> > It is worth discussing if it makes sense to have access to the local >> region >> > through a constraint, though that breaks the idea a little bit, it would >> > certainly be useful and not overly wasteful in terms of runtime. >> > >> > Supposing the feature would be added to talk to the local table, and >> since >> > the puts are going to be serialized on the regionserver (at least to that >> > single row you are trying to update), you will never get a situation >> where >> > the value added is over the threshold. If you were really worried about >> the >> > atomicity of the operation, then when doing the put, first get the >> RowLock, >> > then do the put and release the RowLock. However, that latter method is >> > going to be really slow, so should only be used as a stop gap if the >> > constraint doesn't work as expected, until a patch is made for >> constraints. >> > >> > Feel free to open up a ticket and link it to 4605 for adding the local >> > table access functionality, and we can discuss the de/merits of adding >> the >> > access. >> > >> > -Jesse >> > >> > On Sat, Dec 3, 2011 at 6:24 AM, Suraj Varma <[email protected]> wrote: >> > >> >> I'm looking at the preCheckAndPut / postCheckAndPut api with >> >> coprocessors and I'm wondering ... are these pre/post checks done >> >> _after_ taking the row lock or is the row lock only done within the >> >> checkAndPut api. >> >> >> >> I'm interested in seeing if we can implement something like: >> >> (in pseudo sql) >> >> update table-name >> >> set column-name = new-value >> >> where (column-value - new-value) > threshold-value >> >> >> >> Basically ... I want to enhance the checkAndPut to not just compare >> >> "values" ... but apply an arbitrary function on the value _atomically_ >> >> in the Put call. Multiple threads would be firing these mutations and >> >> I'd like the threshold-value above to never be breached under any >> >> circumstance. >> >> >> >> Is there a solution that can be implemented either via checkAndPut or >> >> using coprocessors preCheckAndPut? If not, would this be a useful >> >> feature to build in HBase? >> >> >> >> Thanks, >> >> --Suraj >> >> >> > >> > >> > >> > -- >> > ------------------- >> > Jesse Yates >> > 240-888-2200 >> > @jesse_yates >>
