{"action":"created","issue":{"url":"https://api.github.com/repos/facebook/rocksdb/issues/1166","repository_url":"https://api.github.com/repos/facebook/rocksdb","labels_url":"https://api.github.com/repos/facebook/rocksdb/issues/1166/labels{/name}","comments_url":"https://api.github.com/repos/facebook/rocksdb/issues/1166/comments","events_url":"https://api.github.com/repos/facebook/rocksdb/issues/1166/events","html_url":"https://github.com/facebook/rocksdb/issues/1166","id":160161817,"number":1166,"title":"Problems with uint64_t in RocksJava","user":{"login":"adamretter","id":1264057,"avatar_url":"https://avatars.githubusercontent.com/u/1264057?v=3","gravatar_id":"","url":"https://api.github.com/users/adamretter","html_url":"https://github.com/adamretter","followers_url":"https://api.github.com/users/adamretter/followers","following_url":"https://api.github.com/users/adamretter/following{/other_user}","gists_url":"https://api.github.com/users/adamretter/gists{/gist_id}","starred_url":"https://api.github.com/users/adamretter/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/adamretter/subscriptions","organizations_url":"https://api.github.com/users/adamretter/orgs","repos_url":"https://api.github.com/users/adamretter/repos","events_url":"https://api.github.com/users/adamretter/events{/privacy}","received_events_url":"https://api.github.com/users/adamretter/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/facebook/rocksdb/labels/bug","name":"bug","color":"fc2929"},{"url":"https://api.github.com/repos/facebook/rocksdb/labels/java-api","name":"java-api","color":"fbca04"},{"url":"https://api.github.com/repos/facebook/rocksdb/labels/question","name":"question","color":"cc317c"}],"state":"open","locked":false,"assignee":{"login":"adamretter","id":1264057,"avatar_url":"https://avatars.githubusercontent.com/u/1264057?v=3","gravatar_id":"","url":"https://api.github.com/users/adamretter","html_url":"https://github.com/adamretter","followers_url":"https://api.github.com/users/adamretter/followers","following_url":"https://api.github.com/users/adamretter/following{/other_user}","gists_url":"https://api.github.com/users/adamretter/gists{/gist_id}","starred_url":"https://api.github.com/users/adamretter/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/adamretter/subscriptions","organizations_url":"https://api.github.com/users/adamretter/orgs","repos_url":"https://api.github.com/users/adamretter/repos","events_url":"https://api.github.com/users/adamretter/events{/privacy}","received_events_url":"https://api.github.com/users/adamretter/received_events","type":"User","site_admin":false},"milestone":null,"comments":6,"created_at":"2016-06-14T11:50:48Z","updated_at":"2016-06-14T18:06:56Z","closed_at":null,"body":"If we look for example at `DBOptions` then we see that there are several options in the C++ API of RocksDB that use `uint64_t` as their type. Unfortunately in RocksJava the `DBOptionsInterface` presents these to the user as a Java `long` which is a two's complement signed 64 bit integer.\r\n\r\nSadly Java has no native support for unsigned integers. However as Java's `long` is 64 bits we can go back and forwards between Java `long` and C++ `uint64_t` without any loss of precision; the issue is that this looks rather ugly to RocksJava users as any value greater than `INT64_MAX` will be wrapped and become a negative value `long` in Java.\r\n\r\nFor example, if we examine `DBOptions::bytes_per_sync`, then when reading this value from RocksJava via `DBOptions#bytesPerSync()` we have the following underlying code performing the conversion from `uint64_t` to `jlong`:\r\n\r\n```C++\r\njlong Java_org_rocksdb_Options_bytesPerSync(\r\n    JNIEnv* env, jobject jobj, jlong jhandle) {\r\n  return reinterpret_cast<rocksdb::Options*>(jhandle)->bytes_per_sync;\r\n}\r\n```\r\n\r\n1. The problem here is that any value between `INT64_MAX` but within the bound of `UINT64_MAX` will appear to the Java user as a negative value, whereas most likely they would have expected a positive value.\r\n\r\nWhen writing this value from RocksJava via `DBOptions#setBytesPerSync(long)` we have the following underlying code performing the conversion from `jlong` to `uint64_t`:\r\n\r\n```C++\r\nvoid Java_org_rocksdb_Options_setBytesPerSync(\r\n    JNIEnv* env, jobject jobj, jlong jhandle, jlong bytes_per_sync) {\r\n  reinterpret_cast<rocksdb::Options*>(jhandle)->bytes_per_sync =\r\n      static_cast<int64_t>(bytes_per_sync);\r\n}\r\n```\r\n\r\n2. The problem here is that the Java user cannot set a positive value for `bytesPerSync` greater than `INT64_MAX` without understanding that they actually need to set the Java `long` to the equivalent negative value.\r\n\r\nIn reality there is not a clean solution to this, perhaps the best option we could hope for would be to add our own `UInt64` Java class that wraps a Java `long` or `byte[]`, and allows construction from a Java `String` or `long`, and serialization. This would at least make the Java interface explicitly express that this is a `uint64_t` and show a positive value in Java on the `toString()`.\r\n\r\n@siying @yhchiang Thoughts?\r\n\r\n\r\n"},"comment":{"url":"https://api.github.com/repos/facebook/rocksdb/issues/comments/225966202","html_url":"https://github.com/facebook/rocksdb/issues/1166#issuecomment-225966202","issue_url":"https://api.github.com/repos/facebook/rocksdb/issues/1166","id":225966202,"user":{"login":"siying","id":5334567,"avatar_url":"https://avatars.githubusercontent.com/u/5334567?v=3","gravatar_id":"","url":"https://api.github.com/users/siying","html_url":"https://github.com/siying","followers_url":"https://api.github.com/users/siying/followers","following_url":"https://api.github.com/users/siying/following{/other_user}","gists_url":"https://api.github.com/users/siying/gists{/gist_id}","starred_url":"https://api.github.com/users/siying/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/siying/subscriptions","organizations_url":"https://api.github.com/users/siying/orgs","repos_url":"https://api.github.com/users/siying/repos","events_url":"https://api.github.com/users/siying/events{/privacy}","received_events_url":"https://api.github.com/users/siying/received_events","type":"User","site_admin":false},"created_at":"2016-06-14T18:06:56Z","updated_at":"2016-06-14T18:06:56Z","body":"@adamretter for the options we have now, no value larger than int32_max makes sense. No guarantee for the future though, as 2GB can make more sense than 8EB."}}
{"actor":{"display_login":"siying"}}