Compare and swap in Berkeley DB JE? - java

I'm looking for an efficient way to implement compare-and-swap operation in Berkeley DB. Right now I'm using really old version, however at first glance even the latest one (distributed from Oracle website) does not have a single method for such operation.
I was looking for a some kind of method like
replace(Transaction, Key, ExpectedValue, NewValue)
with the following semantics: DB gets value associated with a given key, if this value exists and it is equal to ExpectedValue then this value will be changed to NewValue, otherwise method returns unsuccessful OperationStatus.
Looks like there is no method like that, so I'm wondering how is this supposed to be done in the most efficient way.
Right now I'm using the following approach: I do
db.get(null, key) -> {currentValue, version}
db.put(null, key, {currentValue, newRandomIdVersion})
db.get(null, key)
I compare value and version, if they match I do final update erasing old version. If any step fail, the whole process restarts.
I feel that this is very suboptimal - am I wrong?

My solution in update to my question is wrong - however only slight modification is required to make it better.
The solution might be as follows: create separate DB for storing locks that will hold associations of key to some counter. This DB should allow sorted duplicates (so that Database.get would return smallest value associated with a given key). Then use shared monotonically increasing counter. Multiple threads attempting to do CAS will get values from this counter and store key-value pairs in that lock DB. Thread that stored lowest value associated with a key, assumes that it has permission to write and goes ahead with compare-and-swap for desired record, then deletes its entry from the lock DB, other threads simply retry.

Related

Mongodb document format consistency

I am relatively new to Mongodb and I have an idea in mind but not sure how to go about it.
What I would like to do is essentially hash a mongodb document (preferably it's Json format so it is not database specific) and store that hash somewhere with a reference to that specific document. This needs to allow me to retrieve the document in the future via a query and compare against the stored hash.
My idea is to get the json representation of the DBObject, hash it and then add the hash as a field to that specific document before persisting it. Then when querying for the object, make sure to exclude the hash field from the answer so the returned DBObject includes the same hash.
1 - Does mongodb always return a consistent DBObject format which will always convert to the same json so that the hash would always be the same
2 - Would such an implementation even be viable? As in storing the hash with the object itself, essentially changing the object (thus making the hash invalid) but getting around by not retrieving that field in the response
3 - If the implementation would not work, what would be the simplest way to store the hash, another object with a reference to the original document?
1- Does mongodb always return a consistent DBObject format which will always convert to the same json so that the hash would always be the same. - No Mongo does not guarantee the order so the json can be different based on what kind of updates were done on the document. There is no guarantee that the field order will be consistent, or the same, after an update. If no such order changing updates were done on it then the order should be preserved MongoDB update on Field Order .
But when you serialize the json into an object using Jackson or something else it will serialize to the same object and should have the same hash.
2 - Would such an implementation even be viable? As in storing the hash with the object itself, essentially changing the object (thus making the hash invalid) but getting around by not retrieving that field in the response.
Looks like from this answer you can use Jakson or Gson to hash the json object, even though it is not ordered.
excluding a field should not be a problem.
If you store the hash as a field in the object itself all the write queries that save ( which is an overwrite of the entire document ) will have to write the hash into it. If any of them fail to do so the hash will be lost.
An update query will have another problem since along with changing the data it also has to update the hash of the document. So this will have to involve reading the object, modifying it, computing the hash and storing it back. You will not be able to use the primitive update queries.
If you make the hash as the primary key which is _id field that would mitigate this problem although you probably need it for something else.
3- The simplest way would be to store the _id of the document to be hashed into another collection along with the hash as the _id of the new collection.
{
"_id":<hash code of docuemnt>,
"refer":<_id of the document to be hashed>
}
This would involve multiple read writes which will hurt performance and depending on your use case it
Mongo according to me is a simplistic database designed to store and retrieve objects. If you have the need to do something complicated with it other than retrieving fast and writing its probably not fit for the task.

Java String hashcode as Mysql ID

The scenario is something like this description.
I've the typical mysql table for the users storage, currently, the user ID is one integer set as autoincrement. Very much of the API rest interfaces works with the user alias (that's unique) to find the user, then, I'm thinking implement the user ID with the alias.hashcode() (that's one integer) to find diretly for ID every times.
Is a good idea implement Mysql ID with one java String hashcode?. Would enhance the performance?
I don't think it's a great idea. The pigeon hole principle states (from Wikipedia) if n items are put into m containers, with n > m, then at least one container must contain more than one item. Basically, your solution cannot handle collisions and collisions are very possible with hashing.
Don't use String hashCode as your ID, since it's not unique. Two different Strings may have the same hashCode. I'm assuming your ID should be unique.
Just add an index on the alias column, and query the db by alias directly. There are two problems with using alias hash code or other derivatives as an id. First, as others pointed out, hash codes are not be unique (this can be almost solved by changing the id type to string, and using a digest instead of the hash. Collisions with digests, while still possible, are extremely unlikely). Second, if the user changes his alias, the value will get out of sync with the id. If functionality of your application is such, that this situation is either impossible or unimportant, then you don't really need an id at all, and can identify users by alias directly.

Automatically compute hash value for password field

Is there any way to tell Glassfish that the hash value for a certain data member of an entity class should be calculated and stored in the database instead of the original value?
If you modify the getter of a field to produce its hash instead of original value, you might end up with the hash stored instead.
If your database has a hash function, other option is to issue native query using entitiy manager.
Give it a try

How can I atomically add a new key to google appengine's memcache?

I'd like to atomically add a new key to google appengine's memcache service using the Java API. This means that the put operation should fail (e.g. throw an exception or return false ) if the key is already present in the memcache, preventing concurrent additions (which would result in overwriting) to the memcache.
I don't see how this can be accomplished with the getIdentifiable / putIfUntouched pair of methods. Also, synchronize does not help because I want control concurrency across different instances of my servlet.
You want to put with SetPolicy.ADD_ONLY_IF_NOT_PRESENT that will only write a value if the key does not exist already.
boolean put(java.lang.Object key,
java.lang.Object value,
Expiration expires,
MemcacheService.SetPolicy policy)
The return value will tell you if a value already existed.

How to get the key when a corresponding value is used instead?

I am using Android 2.1 SDK, the application reads from the Sqlite database, a table that has two columns, an id, and a string.
I read in this into a HashMap<Long, String>, the value part of it gets displayed in a List, now, I wish to obtain the key value, so I cooked up this simple routine:
private Map.Entry<Long, String> getEntry(String sValue){
for (Iterator<Map.Entry<Long, String>> itMap = this.dbMap.entrySet().iterator(); itMap.hasNext();) {
Map.Entry<Long, String> curr = itMap.next();
if (curr.getValue().equalsIgnoreCase(sValue)) return curr;
}
return null;
}
My problem is being conscious of cpu cycles being chewed up in respect to Android, battery/cpu time, in looking for the value in the HashMap, that could be seen as a potential cycles of cpu lost.
Is there an easier and more efficient way of doing this instead of iterating?
The reasoning is that I can home in on the id, and directly delete the record from the table or even update it.
Um... it looks like the String should be the key, and the id the value. Which assumes that the Strings are unique, but so does your code.
Alternatively, can't your list keep the ID that corresponds to an entry around invisibly? This is how you'd usually do it (e.g. in Swing or in a HTML select).
Realistically, the only way to avoid having to iterate through is to keep two HashMaps (i.e. pay the memory cost) where one HashMap is the reverse of the first. You can create the reverse-lookup HashMap when you create your forward-lookup HashMap without having to loop through your data twice. That should give you low constant time access in both directions.
If you use an Adapter you can access the ID using the getItemID() method.

Categories

Resources