Set or Return Current Value
I'm using the spymemcached client in Java to attempt to set a key if it doesn't already exist.
If I could also return the existing value if it does exist then I'll be sorted.
Is this possible?
Thanks
Most functions have asynch counterparts, so you can certainly do all of the operations asynch, put the returned Futures in a collection, then look over the Futures for status. That'll make your interaction with the server less synchronous.
Under the covers, that's what the bulk operations do. We have bulk operations for the things that seem sort of bulk oriented. For instance, getting a bunch of keys that you know up front and then retrieving them out of a Map later. There's no direct equivalent for what to do with a Future. That's a bit application specific. Sometimes you just don't care, other times you need to check on the status.
Proceed with a bit of caution here. Creating Future requests happens at memory allocation speed, not network utilization speed. One thing you can do is use a bounded queue to ensure you don't overrun JVM memory.
Hope that helps,
Matt
This is two operations at the protocol level, an add followed by a get. It could easily be wrappered in a function, but the return values would be of very different types.
Thanks for the tip. I completely overlooked doing that for some reason.
Is it possible to do a CAS-delete. Where the key will only be deleted if the CAS value for the key matches the one provided?
At the moment this is the only consistency hole in my application so I'd really like to patch it up.
Thanks
I might be overlooking something again, but there is no asyncIncr(key,by,def). Is there a reason for this?
I can't find much documentation about incrementing with Membase. Is it possible to use an add to create an incremental key?
Just answered my own question about adding numeric values. I didn't think to try adding a numerical String.
There is no check and delete operation. What is the use case in your application for wanting to delete an item only if the value hasn't changed? I think the only option you have with memcached/Mmebase is to just delete the ley. If it exists the delete will be a success and if the key doesn't exist the delete will be a failure.
The use case is as follows:
A pointer key (P) to object (O) is being allocated to a particular key (e.g. X)
P = O
X = P
The application "gets" X. The application checks whether or not it should be deleted, but if another process has changed the value it in the meantime then it's no longer this process's responsibility and it may not need deleting.
Therefore I only want to delete key X if it is equal to P.
I'm going to attempt to answer this. If it doesn't fit your use case let me know. This example is using telnet.
I think the best case scenario is to do this with 2-3 calls to memcached.
So we have a key X and X's value is the name of another key, P. In our application we start by setting X's value to P. From here we do a gets.
gets X
VALUE X 0 1 571818
P
END
We save the cas value and run some application code. At this point the value of X could point to P or it could point to the name of another key. If the value of X is P then we will delete the key, otherwise we will do nothing. We could do another gets.
gets X
VALUE X 0 1 571818
P
END
And then check to see if the CAS value matches the value returned from the previous gets call. If it matches then we delete X, otherwise we do not delete X.
One problem I see here is if X is updated with P. This would cause the CAS to be the different, but the value of X would still be P. If this is an issue then you might just want to compare the value of X each time. You could do this by just doing a get.
I also want to note that there is no way of doing this exact operation without modifying the source code of memcached so your best bet is to figure out a mix of commands that will achieve what you want as I have done above.
The main reason was consistency. Your suggestion is more reliable than just deleting the key every time, but it isn't watertight.
I assume that CAS is a single operation within membase? That is that it doesn't do a get and if the CAS value is the same do a set, which wouldn't account for the possibility of two clients doing so simultaneously. This manual check and set pair is equivalent to your proposed manual check and delete.
The reason for wanting to actually delete the key is so that an add can occur for the same key in the future. X can only be allocated to one object at a time so it must be deleted before another object may allocate it.
If the CAS is different then I also don't want to delete the key. Another solution to this problem would be to set X with the previously acquired CAS value to a value representing empty and then when it comes to reuse it only allow modification if the value of X is equal to this empty value, but this is also not possible in a single operation.
The reason for being so stringent on consistency is that the possibility for an inconsistency would cause havoc within the application.
Thanks for you help so far.
Marcus, I've filed an enhancement request to implement delete+CAS within the client. The server itself will actually support it I believe, just need the implementation on the client side.
Hope that will meet your needs, feel free to vote for the enhancement request: http://www.couchbase.org/issues/browse/SPY-34
Perry
Is there a reason why most functions are lacking bulk counterparts?
Surely it would make sense to package a set of operations into one collection and send it off to the server, then handle the results rather than making a new operation for each individual interaction? Or is there a reason why only retrieving has such functionality?
I'm currently experiencing some terrible performance when adding, CASing and incrementing thousands of values.
Thanks