stringappend2.cc 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. /**
  2. * @author Deon Nicholas (dnicholas@fb.com)
  3. * Copyright 2013 Facebook
  4. */
  5. #include "stringappend2.h"
  6. #include <memory>
  7. #include <string>
  8. #include <assert.h>
  9. #include "rocksdb/slice.h"
  10. #include "rocksdb/merge_operator.h"
  11. #include "utilities/merge_operators.h"
  12. namespace ROCKSDB_NAMESPACE {
  13. // Constructor: also specify the delimiter character.
  14. StringAppendTESTOperator::StringAppendTESTOperator(char delim_char)
  15. : delim_(delim_char) {
  16. }
  17. // Implementation for the merge operation (concatenates two strings)
  18. bool StringAppendTESTOperator::FullMergeV2(
  19. const MergeOperationInput& merge_in,
  20. MergeOperationOutput* merge_out) const {
  21. // Clear the *new_value for writing.
  22. merge_out->new_value.clear();
  23. if (merge_in.existing_value == nullptr && merge_in.operand_list.size() == 1) {
  24. // Only one operand
  25. merge_out->existing_operand = merge_in.operand_list.back();
  26. return true;
  27. }
  28. // Compute the space needed for the final result.
  29. size_t numBytes = 0;
  30. for (auto it = merge_in.operand_list.begin();
  31. it != merge_in.operand_list.end(); ++it) {
  32. numBytes += it->size() + 1; // Plus 1 for the delimiter
  33. }
  34. // Only print the delimiter after the first entry has been printed
  35. bool printDelim = false;
  36. // Prepend the *existing_value if one exists.
  37. if (merge_in.existing_value) {
  38. merge_out->new_value.reserve(numBytes + merge_in.existing_value->size());
  39. merge_out->new_value.append(merge_in.existing_value->data(),
  40. merge_in.existing_value->size());
  41. printDelim = true;
  42. } else if (numBytes) {
  43. merge_out->new_value.reserve(
  44. numBytes - 1); // Minus 1 since we have one less delimiter
  45. }
  46. // Concatenate the sequence of strings (and add a delimiter between each)
  47. for (auto it = merge_in.operand_list.begin();
  48. it != merge_in.operand_list.end(); ++it) {
  49. if (printDelim) {
  50. merge_out->new_value.append(1, delim_);
  51. }
  52. merge_out->new_value.append(it->data(), it->size());
  53. printDelim = true;
  54. }
  55. return true;
  56. }
  57. bool StringAppendTESTOperator::PartialMergeMulti(
  58. const Slice& /*key*/, const std::deque<Slice>& /*operand_list*/,
  59. std::string* /*new_value*/, Logger* /*logger*/) const {
  60. return false;
  61. }
  62. // A version of PartialMerge that actually performs "partial merging".
  63. // Use this to simulate the exact behaviour of the StringAppendOperator.
  64. bool StringAppendTESTOperator::_AssocPartialMergeMulti(
  65. const Slice& /*key*/, const std::deque<Slice>& operand_list,
  66. std::string* new_value, Logger* /*logger*/) const {
  67. // Clear the *new_value for writing
  68. assert(new_value);
  69. new_value->clear();
  70. assert(operand_list.size() >= 2);
  71. // Generic append
  72. // Determine and reserve correct size for *new_value.
  73. size_t size = 0;
  74. for (const auto& operand : operand_list) {
  75. size += operand.size();
  76. }
  77. size += operand_list.size() - 1; // Delimiters
  78. new_value->reserve(size);
  79. // Apply concatenation
  80. new_value->assign(operand_list.front().data(), operand_list.front().size());
  81. for (std::deque<Slice>::const_iterator it = operand_list.begin() + 1;
  82. it != operand_list.end(); ++it) {
  83. new_value->append(1, delim_);
  84. new_value->append(it->data(), it->size());
  85. }
  86. return true;
  87. }
  88. const char* StringAppendTESTOperator::Name() const {
  89. return "StringAppendTESTOperator";
  90. }
  91. std::shared_ptr<MergeOperator>
  92. MergeOperators::CreateStringAppendTESTOperator() {
  93. return std::make_shared<StringAppendTESTOperator>(',');
  94. }
  95. } // namespace ROCKSDB_NAMESPACE