comparator.cc 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. // Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
  2. // This source code is licensed under both the GPLv2 (found in the
  3. // COPYING file in the root directory) and Apache 2.0 License
  4. // (found in the LICENSE.Apache file in the root directory).
  5. //
  6. // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
  7. // Use of this source code is governed by a BSD-style license that can be
  8. // found in the LICENSE file. See the AUTHORS file for names of contributors.
  9. #include "rocksdb/comparator.h"
  10. #include <algorithm>
  11. #include <cstdint>
  12. #include <memory>
  13. #include <mutex>
  14. #include <sstream>
  15. #include "db/dbformat.h"
  16. #include "port/lang.h"
  17. #include "port/port.h"
  18. #include "rocksdb/convenience.h"
  19. #include "rocksdb/slice.h"
  20. #include "rocksdb/utilities/customizable_util.h"
  21. #include "rocksdb/utilities/object_registry.h"
  22. #include "util/coding.h"
  23. namespace ROCKSDB_NAMESPACE {
  24. namespace {
  25. class BytewiseComparatorImpl : public Comparator {
  26. public:
  27. BytewiseComparatorImpl() = default;
  28. static const char* kClassName() { return "leveldb.BytewiseComparator"; }
  29. const char* Name() const override { return kClassName(); }
  30. int Compare(const Slice& a, const Slice& b) const override {
  31. return a.compare(b);
  32. }
  33. bool Equal(const Slice& a, const Slice& b) const override { return a == b; }
  34. void FindShortestSeparator(std::string* start,
  35. const Slice& limit) const override {
  36. // Find length of common prefix
  37. size_t min_length = std::min(start->size(), limit.size());
  38. size_t diff_index = 0;
  39. while ((diff_index < min_length) &&
  40. ((*start)[diff_index] == limit[diff_index])) {
  41. diff_index++;
  42. }
  43. if (diff_index >= min_length) {
  44. // Do not shorten if one string is a prefix of the other
  45. } else {
  46. uint8_t start_byte = static_cast<uint8_t>((*start)[diff_index]);
  47. uint8_t limit_byte = static_cast<uint8_t>(limit[diff_index]);
  48. if (start_byte >= limit_byte) {
  49. // Cannot shorten since limit is smaller than start or start is
  50. // already the shortest possible.
  51. return;
  52. }
  53. assert(start_byte < limit_byte);
  54. if (diff_index < limit.size() - 1 || start_byte + 1 < limit_byte) {
  55. (*start)[diff_index]++;
  56. start->resize(diff_index + 1);
  57. } else {
  58. // v
  59. // A A 1 A A A
  60. // A A 2
  61. //
  62. // Incrementing the current byte will make start bigger than limit, we
  63. // will skip this byte, and find the first non 0xFF byte in start and
  64. // increment it.
  65. diff_index++;
  66. while (diff_index < start->size()) {
  67. // Keep moving until we find the first non 0xFF byte to
  68. // increment it
  69. if (static_cast<uint8_t>((*start)[diff_index]) <
  70. static_cast<uint8_t>(0xff)) {
  71. (*start)[diff_index]++;
  72. start->resize(diff_index + 1);
  73. break;
  74. }
  75. diff_index++;
  76. }
  77. }
  78. assert(Compare(*start, limit) < 0);
  79. }
  80. }
  81. void FindShortSuccessor(std::string* key) const override {
  82. // Find first character that can be incremented
  83. size_t n = key->size();
  84. for (size_t i = 0; i < n; i++) {
  85. const uint8_t byte = (*key)[i];
  86. if (byte != static_cast<uint8_t>(0xff)) {
  87. (*key)[i] = byte + 1;
  88. key->resize(i + 1);
  89. return;
  90. }
  91. }
  92. // *key is a run of 0xffs. Leave it alone.
  93. }
  94. bool IsSameLengthImmediateSuccessor(const Slice& s,
  95. const Slice& t) const override {
  96. if (s.size() != t.size() || s.size() == 0) {
  97. return false;
  98. }
  99. size_t diff_ind = s.difference_offset(t);
  100. // same slice
  101. if (diff_ind >= s.size()) {
  102. return false;
  103. }
  104. uint8_t byte_s = static_cast<uint8_t>(s[diff_ind]);
  105. uint8_t byte_t = static_cast<uint8_t>(t[diff_ind]);
  106. // first different byte must be consecutive, and remaining bytes must be
  107. // 0xff for s and 0x00 for t
  108. if (byte_s != uint8_t{0xff} && byte_s + 1 == byte_t) {
  109. for (size_t i = diff_ind + 1; i < s.size(); ++i) {
  110. byte_s = static_cast<uint8_t>(s[i]);
  111. byte_t = static_cast<uint8_t>(t[i]);
  112. if (byte_s != uint8_t{0xff} || byte_t != uint8_t{0x00}) {
  113. return false;
  114. }
  115. }
  116. return true;
  117. } else {
  118. return false;
  119. }
  120. }
  121. bool CanKeysWithDifferentByteContentsBeEqual() const override {
  122. return false;
  123. }
  124. using Comparator::CompareWithoutTimestamp;
  125. int CompareWithoutTimestamp(const Slice& a, bool /*a_has_ts*/, const Slice& b,
  126. bool /*b_has_ts*/) const override {
  127. return a.compare(b);
  128. }
  129. bool EqualWithoutTimestamp(const Slice& a, const Slice& b) const override {
  130. return a == b;
  131. }
  132. };
  133. class ReverseBytewiseComparatorImpl : public BytewiseComparatorImpl {
  134. public:
  135. ReverseBytewiseComparatorImpl() = default;
  136. static const char* kClassName() {
  137. return "rocksdb.ReverseBytewiseComparator";
  138. }
  139. const char* Name() const override { return kClassName(); }
  140. int Compare(const Slice& a, const Slice& b) const override {
  141. return -a.compare(b);
  142. }
  143. void FindShortestSeparator(std::string* start,
  144. const Slice& limit) const override {
  145. // Find length of common prefix
  146. size_t min_length = std::min(start->size(), limit.size());
  147. size_t diff_index = 0;
  148. while ((diff_index < min_length) &&
  149. ((*start)[diff_index] == limit[diff_index])) {
  150. diff_index++;
  151. }
  152. assert(diff_index <= min_length);
  153. if (diff_index == min_length) {
  154. // Do not shorten if one string is a prefix of the other
  155. //
  156. // We could handle cases like:
  157. // V
  158. // A A 2 X Y
  159. // A A 2
  160. // in a similar way as BytewiseComparator::FindShortestSeparator().
  161. // We keep it simple by not implementing it. We can come back to it
  162. // later when needed.
  163. } else {
  164. uint8_t start_byte = static_cast<uint8_t>((*start)[diff_index]);
  165. uint8_t limit_byte = static_cast<uint8_t>(limit[diff_index]);
  166. if (start_byte > limit_byte && diff_index < start->size() - 1) {
  167. // Case like
  168. // V
  169. // A A 3 A A
  170. // A A 1 B B
  171. //
  172. // or
  173. // v
  174. // A A 2 A A
  175. // A A 1 B B
  176. // In this case "AA2" will be good.
  177. #ifndef NDEBUG
  178. std::string old_start = *start;
  179. #endif
  180. start->resize(diff_index + 1);
  181. #ifndef NDEBUG
  182. assert(old_start >= *start);
  183. #endif
  184. assert(Slice(*start).compare(limit) > 0);
  185. }
  186. }
  187. }
  188. void FindShortSuccessor(std::string* /*key*/) const override {
  189. // Don't do anything for simplicity.
  190. }
  191. bool IsSameLengthImmediateSuccessor(const Slice& s,
  192. const Slice& t) const override {
  193. // Always returning false to prevent surfacing design flaws in
  194. // auto_prefix_mode
  195. (void)s, (void)t;
  196. return false;
  197. // "Correct" implementation:
  198. // return BytewiseComparatorImpl::IsSameLengthImmediateSuccessor(t, s);
  199. }
  200. bool CanKeysWithDifferentByteContentsBeEqual() const override {
  201. return false;
  202. }
  203. using Comparator::CompareWithoutTimestamp;
  204. int CompareWithoutTimestamp(const Slice& a, bool /*a_has_ts*/, const Slice& b,
  205. bool /*b_has_ts*/) const override {
  206. return -a.compare(b);
  207. }
  208. };
  209. // Comparator with 64-bit integer timestamp.
  210. // We did not performance test this yet.
  211. template <typename TComparator>
  212. class ComparatorWithU64TsImpl : public Comparator {
  213. static_assert(std::is_base_of<Comparator, TComparator>::value,
  214. "template type must be a inherited type of comparator");
  215. public:
  216. explicit ComparatorWithU64TsImpl() : Comparator(/*ts_sz=*/sizeof(uint64_t)) {
  217. assert(cmp_without_ts_.timestamp_size() == 0);
  218. }
  219. static const char* kClassName() {
  220. static std::string class_name = kClassNameInternal();
  221. return class_name.c_str();
  222. }
  223. const char* Name() const override { return kClassName(); }
  224. // The comparator that compares the user key without timestamp part is treated
  225. // as the root comparator.
  226. const Comparator* GetRootComparator() const override {
  227. return &cmp_without_ts_;
  228. }
  229. void FindShortSuccessor(std::string*) const override {}
  230. void FindShortestSeparator(std::string*, const Slice&) const override {}
  231. int Compare(const Slice& a, const Slice& b) const override {
  232. int ret = CompareWithoutTimestamp(a, b);
  233. size_t ts_sz = timestamp_size();
  234. if (ret != 0) {
  235. return ret;
  236. }
  237. // Compare timestamp.
  238. // For the same user key with different timestamps, larger (newer) timestamp
  239. // comes first.
  240. return -CompareTimestamp(ExtractTimestampFromUserKey(a, ts_sz),
  241. ExtractTimestampFromUserKey(b, ts_sz));
  242. }
  243. Slice GetMaxTimestamp() const override { return MaxU64Ts(); }
  244. Slice GetMinTimestamp() const override { return MinU64Ts(); }
  245. std::string TimestampToString(const Slice& timestamp) const override {
  246. assert(timestamp.size() == sizeof(uint64_t));
  247. uint64_t ts = 0;
  248. DecodeU64Ts(timestamp, &ts).PermitUncheckedError();
  249. return std::to_string(ts);
  250. }
  251. using Comparator::CompareWithoutTimestamp;
  252. int CompareWithoutTimestamp(const Slice& a, bool a_has_ts, const Slice& b,
  253. bool b_has_ts) const override {
  254. const size_t ts_sz = timestamp_size();
  255. assert(!a_has_ts || a.size() >= ts_sz);
  256. assert(!b_has_ts || b.size() >= ts_sz);
  257. Slice lhs = a_has_ts ? StripTimestampFromUserKey(a, ts_sz) : a;
  258. Slice rhs = b_has_ts ? StripTimestampFromUserKey(b, ts_sz) : b;
  259. return cmp_without_ts_.Compare(lhs, rhs);
  260. }
  261. int CompareTimestamp(const Slice& ts1, const Slice& ts2) const override {
  262. assert(ts1.size() == sizeof(uint64_t));
  263. assert(ts2.size() == sizeof(uint64_t));
  264. uint64_t lhs = DecodeFixed64(ts1.data());
  265. uint64_t rhs = DecodeFixed64(ts2.data());
  266. if (lhs < rhs) {
  267. return -1;
  268. } else if (lhs > rhs) {
  269. return 1;
  270. } else {
  271. return 0;
  272. }
  273. }
  274. private:
  275. static std::string kClassNameInternal() {
  276. std::stringstream ss;
  277. ss << TComparator::kClassName() << ".u64ts";
  278. return ss.str();
  279. }
  280. TComparator cmp_without_ts_;
  281. };
  282. } // namespace
  283. const Comparator* BytewiseComparator() {
  284. STATIC_AVOID_DESTRUCTION(BytewiseComparatorImpl, bytewise);
  285. return &bytewise;
  286. }
  287. const Comparator* ReverseBytewiseComparator() {
  288. STATIC_AVOID_DESTRUCTION(ReverseBytewiseComparatorImpl, rbytewise);
  289. return &rbytewise;
  290. }
  291. const Comparator* BytewiseComparatorWithU64Ts() {
  292. STATIC_AVOID_DESTRUCTION(ComparatorWithU64TsImpl<BytewiseComparatorImpl>,
  293. comp_with_u64_ts);
  294. return &comp_with_u64_ts;
  295. }
  296. const Comparator* ReverseBytewiseComparatorWithU64Ts() {
  297. STATIC_AVOID_DESTRUCTION(
  298. ComparatorWithU64TsImpl<ReverseBytewiseComparatorImpl>, comp_with_u64_ts);
  299. return &comp_with_u64_ts;
  300. }
  301. Status DecodeU64Ts(const Slice& ts, uint64_t* int_ts) {
  302. if (ts.size() != sizeof(uint64_t)) {
  303. return Status::InvalidArgument("U64Ts timestamp size mismatch.");
  304. }
  305. *int_ts = DecodeFixed64(ts.data());
  306. return Status::OK();
  307. }
  308. Slice EncodeU64Ts(uint64_t ts, std::string* ts_buf) {
  309. char buf[sizeof(ts)];
  310. EncodeFixed64(buf, ts);
  311. ts_buf->assign(buf, sizeof(buf));
  312. return Slice(*ts_buf);
  313. }
  314. Slice MaxU64Ts() {
  315. static constexpr char kTsMax[] = "\xff\xff\xff\xff\xff\xff\xff\xff";
  316. return Slice(kTsMax, sizeof(uint64_t));
  317. }
  318. Slice MinU64Ts() {
  319. static constexpr char kTsMin[] = "\x00\x00\x00\x00\x00\x00\x00\x00";
  320. return Slice(kTsMin, sizeof(uint64_t));
  321. }
  322. static int RegisterBuiltinComparators(ObjectLibrary& library,
  323. const std::string& /*arg*/) {
  324. library.AddFactory<const Comparator>(
  325. BytewiseComparatorImpl::kClassName(),
  326. [](const std::string& /*uri*/,
  327. std::unique_ptr<const Comparator>* /*guard*/,
  328. std::string* /*errmsg*/) { return BytewiseComparator(); });
  329. library.AddFactory<const Comparator>(
  330. ReverseBytewiseComparatorImpl::kClassName(),
  331. [](const std::string& /*uri*/,
  332. std::unique_ptr<const Comparator>* /*guard*/,
  333. std::string* /*errmsg*/) { return ReverseBytewiseComparator(); });
  334. library.AddFactory<const Comparator>(
  335. ComparatorWithU64TsImpl<BytewiseComparatorImpl>::kClassName(),
  336. [](const std::string& /*uri*/,
  337. std::unique_ptr<const Comparator>* /*guard*/,
  338. std::string* /*errmsg*/) { return BytewiseComparatorWithU64Ts(); });
  339. library.AddFactory<const Comparator>(
  340. ComparatorWithU64TsImpl<ReverseBytewiseComparatorImpl>::kClassName(),
  341. [](const std::string& /*uri*/,
  342. std::unique_ptr<const Comparator>* /*guard*/,
  343. std::string* /*errmsg*/) {
  344. return ReverseBytewiseComparatorWithU64Ts();
  345. });
  346. return 4;
  347. }
  348. Status Comparator::CreateFromString(const ConfigOptions& config_options,
  349. const std::string& value,
  350. const Comparator** result) {
  351. static std::once_flag once;
  352. std::call_once(once, [&]() {
  353. RegisterBuiltinComparators(*(ObjectLibrary::Default().get()), "");
  354. });
  355. std::string id;
  356. std::unordered_map<std::string, std::string> opt_map;
  357. Status status = Customizable::GetOptionsMap(config_options, *result, value,
  358. &id, &opt_map);
  359. if (!status.ok()) { // GetOptionsMap failed
  360. return status;
  361. }
  362. if (id == BytewiseComparatorImpl::kClassName()) {
  363. *result = BytewiseComparator();
  364. } else if (id == ReverseBytewiseComparatorImpl::kClassName()) {
  365. *result = ReverseBytewiseComparator();
  366. } else if (id ==
  367. ComparatorWithU64TsImpl<BytewiseComparatorImpl>::kClassName()) {
  368. *result = BytewiseComparatorWithU64Ts();
  369. } else if (id == ComparatorWithU64TsImpl<
  370. ReverseBytewiseComparatorImpl>::kClassName()) {
  371. *result = ReverseBytewiseComparatorWithU64Ts();
  372. } else if (value.empty()) {
  373. // No Id and no options. Clear the object
  374. *result = nullptr;
  375. return Status::OK();
  376. } else if (id.empty()) { // We have no Id but have options. Not good
  377. return Status::NotSupported("Cannot reset object ", id);
  378. } else {
  379. status = config_options.registry->NewStaticObject(id, result);
  380. if (!status.ok()) {
  381. if (config_options.ignore_unsupported_options &&
  382. status.IsNotSupported()) {
  383. return Status::OK();
  384. } else {
  385. return status;
  386. }
  387. } else {
  388. Comparator* comparator = const_cast<Comparator*>(*result);
  389. status =
  390. Customizable::ConfigureNewObject(config_options, comparator, opt_map);
  391. }
  392. }
  393. return status;
  394. }
  395. } // namespace ROCKSDB_NAMESPACE