getKey in FoundationDB returns unexpected result - java

I trying to find a key in some Subspace at FoundationDB with getKey and KeySelector. In case if result exists in Subspace it works pretty well.
val key = new Tuple().add(3)
val subspace = new Subspace(new Tuple().add("test-subspace"))
tr.set(key.pack(), new Tuple().pack())
tr.set(subspace.pack(key), new Tuple().pack())
tr.getKey(KeySelector.firstGreaterOrEqual(subspace.pack(key)))
.thenApply[Tuple] { result =>
println(Tuple.fromBytes(result)) // ("test-subspace", 3)
subspace.unpack(result) // (3)
}
In the same time, if key does not exist in target subspace, it returns me key that was found in default subspace. Which is not what I expected...
val key = new Tuple().add(3)
val subspace = new Subspace(new Tuple().add("test-subspace"))
tr.set(key.pack(), new Tuple().pack())
tr.getKey(KeySelector.firstGreaterOrEqual(subspace.pack(key)))
.thenApply[Tuple] { result =>
println(Tuple.fromBytes(result)) // (3)
subspace.unpack(result) // Cannot unpack key that is not contained in subspace.
}
Also, if db empty, getKey instead of returning null, returns some weird byte array which cannot be parsed by Tuple.fromBytes.
val key = new Tuple().add("my-key")
tr.getKey(KeySelector.firstGreaterOrEqual(key.pack()))
.thenApply[Tuple] { result =>
println(result == null) // false
Tuple.fromBytes(result) // throws java.lang.IllegalArgumentException: Unknown tuple data type -1 at index 0
}
How should I handle situations when target subspaces do not contain the search result?

To add on to what Guarav said, when a key selector resolves to a key before the beginning of the database, it returns the empty key (''). If the key resolves past the end of the database, you'll get '\xff' in a normal transaction or '\xff\xff' if your transaction is allowed to read system keys. This is mentioned briefly at the end of the key selector documentation here.
As for not returning a result outside of your subspace, to do so would probably require getKey accepting a bound key parameter that restricts searches beyond that key. It doesn't currently have that parameter, but getRange does and can be used to perform the same query if you use a limit of 1. For example, you could do:
tr.getRange(KeySelector.firstGreaterOrEqual(subspace.pack(key)), subspace.range().end, 1)
In this case, the result will either have a key if one could be found in the subspace matching your key selector or will be empty if one could not. Of course, you'll also get back the value in this query.

This is expected behavior. Keyselector returns you the key that matches the condition - in this case first key that is greater or equal to the passed byte[]. You would need to check if returned key is valid as per your subspace requirement - by using subspace.contains() or any other validation on the returned key.
Same explanation for the second question- the returned key could be some special pre-existing row in the db, that is not created using tuple layer. Hence it cannot be parsed using tuple layer. You need to check for key validity by using subspace.contains or some similar check.

Related

How to add new key to map in Firestore

I want to add new key to a map. memberFees is a field of a document under collection named Faculty
I want to store only the key of each member fee inside the memberFees map.
Here is an example of my memberFees map:
I only added that keys in the example manually.
This is what I did:
writeBatches.get(batchIndex).update(db.collection("Faculty")
.document(faculty.getId()), "memberFees/" + memberFeeId, true);
This code throws an error:
java.lang.IllegalArgumentException: Invalid document reference. Document references must have an even number of segments, but Faculty/7DEj7mlTPBf3cVSCtQO3/memberFees has 3
at com.google.firebase.firestore.DocumentReference.forPath(DocumentReference.java:81)
When updating a nested field, use . to separate the field names. Your code uses /, which Firestore interprets as a subcollection.
So:
writeBatches.get(batchIndex).update(db.collection("Faculty")
.document(faculty.getId()), "memberFees." + memberFeeId, true)
// 👆

How to assert that a entry exist in the HashMap instead of separately asserting using containKey() and containValue()

I got a Hashmap parsed from the XML document and wanted to check if a list/set of entries exist.
hashMap.entrySet() -> returns set of entry and I want to assert "key1":"value1" exist in this set.
How can this be done?
Reference from stack overflow show containsKey and containsValue but not containsEntry.
References:
Search if specified key and value exists
An Entry is nothing more then the Key and the Value associated with it.
So if you want to check if an specfic Key has an Specific Value associated with it just do this:
SomeObject actualValue = map.get(key)
if(!expectedValue.equals(actualValue))
{
//Key has other Value associated with it
}
else
{
//Key has the expected Value
}

Delete all versions of an object S3 using java

I want to delete all versions of an object with a given key using software.amazon.awssdk.s3 v2.
So far I found out there is no such deleteAllVersions(key), you have to get all versionIds of your object and iterate and delete each version.
The next hurdle is, there is no such listAllVersions(key), only a listAllVersions(prefix). So if I want to listAllVersions("a") of object "a" with prefix "a" as filter, I also get all version of "aa", "ab", "ac" and so on.
It is now possible to iterate an ignore all objects not having exactly key "a". But how to handle a truncated response?
How to delete all versions of an object with a specific key, including versions marked deleted?
Use ListObjectVersionsIterable returned by listObjectVersionsPaginator:
//Pre-filter with prefix
ListObjectVersionsRequest listRequest = ListObjectVersionsRequest.builder().bucket(bucketName).prefix(key).build();
ListObjectVersionsIterable responses = s3Client.listObjectVersionsPaginator(listRequest);
for (ObjectVersion objectVersion : responses.versions())
{
//Filter pre-filtered result
if (objectVersion.key().equals(key))
{
DeleteObjectRequest deleteRequest = DeleteObjectRequest.builder().bucket(bucketName).key(key).versionId(versionId).build();
DeleteObjectResponse response = s3Client.deleteObject(deleteRequest);
}
}
The Paginator will handle the calls internally: https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3Client.html#listObjectVersionsPaginator-software.amazon.awssdk.services.s3.model.ListObjectVersionsRequest-

Hazelcast IMap delete, put and then get immediately for a specific key returns old data

In Hazelcast IMap when I delete a certain key and immediately add the same key with different data and then get that data in less than a second, Hazelcast IMap return old data.
For example
1) I am deleting a key with value {key : String, value : serialized object}
2) Now I add the value against the same key in less than a second with value {key : String, value : serialized object}
3) At this time I try to get the key get{key : String} which return the same value as in point 1.
To avoid this error(workaround), I have tried adding Thread.sleep(1000L). This seems to work but doesn't provide consistency.
Also used evict, remove methods for IMap. Nothing seems to work in this case.
Hazelcast.xml configuration is default config.
At Client side hazelcastClient.xml is also with default config.
method api()
{
if(userIsAlreadyLogin)
{
forcelogout()
}
handleValidUserlogin()
}
method forcelogout()
{
removeUserDetails()
}
removeUserDetails()
{
IMap.lock()
IMap.delete(key : String, value : serialized object)
IMap.unlock()
}
method handleValidUserlogin()
{
IMap.get() //Printing values after deletion
IMap.put(key : String, value : serialized object)
IMap.get()
}

Removing an entry out of an Attributes map

I want to remove entrys out of an attribute map. The problem is that the remove method can't match the key I search for:
final Attributes attributes = manifest.getMainAttributes();
symbolicName = getAttributeValue(attributes, "Bundle-SymbolicName");
attributes.remove("Bundle-SymbolicName");
When i run that code, the entry with the key "Bundle-SymbolicName" (and every other i try to remove) is still in attributes.
In the debugger i can evaluate the following expressions:
attributes.getValue("Bundle-Version") = 0.1.0.qualifier
attributes.containsKey("Bundle-Version") = false
attributes.remove("Bundle-Version") returns null (Returns the previous attribute value, or null if none.)
Is this a problem with typecasting?
RealSkeptic did answer my question: The keys of Attributes are not strings. I need to use the type Attributes.Name

Categories