comparator.cc 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  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 <stdint.h>
  11. #include <algorithm>
  12. #include <memory>
  13. #include "logging/logging.h"
  14. #include "port/port.h"
  15. #include "rocksdb/slice.h"
  16. namespace ROCKSDB_NAMESPACE {
  17. namespace {
  18. class BytewiseComparatorImpl : public Comparator {
  19. public:
  20. BytewiseComparatorImpl() { }
  21. const char* Name() const override { return "leveldb.BytewiseComparator"; }
  22. int Compare(const Slice& a, const Slice& b) const override {
  23. return a.compare(b);
  24. }
  25. bool Equal(const Slice& a, const Slice& b) const override { return a == b; }
  26. void FindShortestSeparator(std::string* start,
  27. const Slice& limit) const override {
  28. // Find length of common prefix
  29. size_t min_length = std::min(start->size(), limit.size());
  30. size_t diff_index = 0;
  31. while ((diff_index < min_length) &&
  32. ((*start)[diff_index] == limit[diff_index])) {
  33. diff_index++;
  34. }
  35. if (diff_index >= min_length) {
  36. // Do not shorten if one string is a prefix of the other
  37. } else {
  38. uint8_t start_byte = static_cast<uint8_t>((*start)[diff_index]);
  39. uint8_t limit_byte = static_cast<uint8_t>(limit[diff_index]);
  40. if (start_byte >= limit_byte) {
  41. // Cannot shorten since limit is smaller than start or start is
  42. // already the shortest possible.
  43. return;
  44. }
  45. assert(start_byte < limit_byte);
  46. if (diff_index < limit.size() - 1 || start_byte + 1 < limit_byte) {
  47. (*start)[diff_index]++;
  48. start->resize(diff_index + 1);
  49. } else {
  50. // v
  51. // A A 1 A A A
  52. // A A 2
  53. //
  54. // Incrementing the current byte will make start bigger than limit, we
  55. // will skip this byte, and find the first non 0xFF byte in start and
  56. // increment it.
  57. diff_index++;
  58. while (diff_index < start->size()) {
  59. // Keep moving until we find the first non 0xFF byte to
  60. // increment it
  61. if (static_cast<uint8_t>((*start)[diff_index]) <
  62. static_cast<uint8_t>(0xff)) {
  63. (*start)[diff_index]++;
  64. start->resize(diff_index + 1);
  65. break;
  66. }
  67. diff_index++;
  68. }
  69. }
  70. assert(Compare(*start, limit) < 0);
  71. }
  72. }
  73. void FindShortSuccessor(std::string* key) const override {
  74. // Find first character that can be incremented
  75. size_t n = key->size();
  76. for (size_t i = 0; i < n; i++) {
  77. const uint8_t byte = (*key)[i];
  78. if (byte != static_cast<uint8_t>(0xff)) {
  79. (*key)[i] = byte + 1;
  80. key->resize(i+1);
  81. return;
  82. }
  83. }
  84. // *key is a run of 0xffs. Leave it alone.
  85. }
  86. bool IsSameLengthImmediateSuccessor(const Slice& s,
  87. const Slice& t) const override {
  88. if (s.size() != t.size() || s.size() == 0) {
  89. return false;
  90. }
  91. size_t diff_ind = s.difference_offset(t);
  92. // same slice
  93. if (diff_ind >= s.size()) return false;
  94. uint8_t byte_s = static_cast<uint8_t>(s[diff_ind]);
  95. uint8_t byte_t = static_cast<uint8_t>(t[diff_ind]);
  96. // first different byte must be consecutive, and remaining bytes must be
  97. // 0xff for s and 0x00 for t
  98. if (byte_s != uint8_t{0xff} && byte_s + 1 == byte_t) {
  99. for (size_t i = diff_ind + 1; i < s.size(); ++i) {
  100. byte_s = static_cast<uint8_t>(s[i]);
  101. byte_t = static_cast<uint8_t>(t[i]);
  102. if (byte_s != uint8_t{0xff} || byte_t != uint8_t{0x00}) {
  103. return false;
  104. }
  105. }
  106. return true;
  107. } else {
  108. return false;
  109. }
  110. }
  111. bool CanKeysWithDifferentByteContentsBeEqual() const override {
  112. return false;
  113. }
  114. int CompareWithoutTimestamp(const Slice& a, const Slice& b) const override {
  115. return a.compare(b);
  116. }
  117. };
  118. class ReverseBytewiseComparatorImpl : public BytewiseComparatorImpl {
  119. public:
  120. ReverseBytewiseComparatorImpl() { }
  121. const char* Name() const override {
  122. return "rocksdb.ReverseBytewiseComparator";
  123. }
  124. int Compare(const Slice& a, const Slice& b) const override {
  125. return -a.compare(b);
  126. }
  127. void FindShortestSeparator(std::string* start,
  128. const Slice& limit) const override {
  129. // Find length of common prefix
  130. size_t min_length = std::min(start->size(), limit.size());
  131. size_t diff_index = 0;
  132. while ((diff_index < min_length) &&
  133. ((*start)[diff_index] == limit[diff_index])) {
  134. diff_index++;
  135. }
  136. assert(diff_index <= min_length);
  137. if (diff_index == min_length) {
  138. // Do not shorten if one string is a prefix of the other
  139. //
  140. // We could handle cases like:
  141. // V
  142. // A A 2 X Y
  143. // A A 2
  144. // in a similar way as BytewiseComparator::FindShortestSeparator().
  145. // We keep it simple by not implementing it. We can come back to it
  146. // later when needed.
  147. } else {
  148. uint8_t start_byte = static_cast<uint8_t>((*start)[diff_index]);
  149. uint8_t limit_byte = static_cast<uint8_t>(limit[diff_index]);
  150. if (start_byte > limit_byte && diff_index < start->size() - 1) {
  151. // Case like
  152. // V
  153. // A A 3 A A
  154. // A A 1 B B
  155. //
  156. // or
  157. // v
  158. // A A 2 A A
  159. // A A 1 B B
  160. // In this case "AA2" will be good.
  161. #ifndef NDEBUG
  162. std::string old_start = *start;
  163. #endif
  164. start->resize(diff_index + 1);
  165. #ifndef NDEBUG
  166. assert(old_start >= *start);
  167. #endif
  168. assert(Slice(*start).compare(limit) > 0);
  169. }
  170. }
  171. }
  172. void FindShortSuccessor(std::string* /*key*/) const override {
  173. // Don't do anything for simplicity.
  174. }
  175. bool CanKeysWithDifferentByteContentsBeEqual() const override {
  176. return false;
  177. }
  178. int CompareWithoutTimestamp(const Slice& a, const Slice& b) const override {
  179. return -a.compare(b);
  180. }
  181. };
  182. }// namespace
  183. const Comparator* BytewiseComparator() {
  184. static BytewiseComparatorImpl bytewise;
  185. return &bytewise;
  186. }
  187. const Comparator* ReverseBytewiseComparator() {
  188. static ReverseBytewiseComparatorImpl rbytewise;
  189. return &rbytewise;
  190. }
  191. } // namespace ROCKSDB_NAMESPACE