作者: 韩晨旭 10225101440 李畅 10225102463
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

257 lines
6.6 KiB

  1. // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file. See the AUTHORS file for names of contributors.
  4. #include "db/version_edit.h"
  5. #include "db/version_set.h"
  6. #include "util/coding.h"
  7. namespace leveldb {
  8. // Tag numbers for serialized VersionEdit. These numbers are written to
  9. // disk and should not be changed.
  10. enum Tag {
  11. kComparator = 1,
  12. kLogNumber = 2,
  13. kNextFileNumber = 3,
  14. kLastSequence = 4,
  15. kCompactPointer = 5,
  16. kDeletedFile = 6,
  17. kNewFile = 7,
  18. // 8 was used for large value refs
  19. kPrevLogNumber = 9
  20. };
  21. void VersionEdit::Clear() {
  22. comparator_.clear();
  23. log_number_ = 0;
  24. prev_log_number_ = 0;
  25. last_sequence_ = 0;
  26. next_file_number_ = 0;
  27. has_comparator_ = false;
  28. has_log_number_ = false;
  29. has_prev_log_number_ = false;
  30. has_next_file_number_ = false;
  31. has_last_sequence_ = false;
  32. deleted_files_.clear();
  33. new_files_.clear();
  34. }
  35. void VersionEdit::EncodeTo(std::string* dst) const {
  36. if (has_comparator_) {
  37. PutVarint32(dst, kComparator);
  38. PutLengthPrefixedSlice(dst, comparator_);
  39. }
  40. if (has_log_number_) {
  41. PutVarint32(dst, kLogNumber);
  42. PutVarint64(dst, log_number_);
  43. }
  44. if (has_prev_log_number_) {
  45. PutVarint32(dst, kPrevLogNumber);
  46. PutVarint64(dst, prev_log_number_);
  47. }
  48. if (has_next_file_number_) {
  49. PutVarint32(dst, kNextFileNumber);
  50. PutVarint64(dst, next_file_number_);
  51. }
  52. if (has_last_sequence_) {
  53. PutVarint32(dst, kLastSequence);
  54. PutVarint64(dst, last_sequence_);
  55. }
  56. for (size_t i = 0; i < compact_pointers_.size(); i++) {
  57. PutVarint32(dst, kCompactPointer);
  58. PutVarint32(dst, compact_pointers_[i].first); // level
  59. PutLengthPrefixedSlice(dst, compact_pointers_[i].second.Encode());
  60. }
  61. for (const auto& deleted_file_kvp : deleted_files_) {
  62. PutVarint32(dst, kDeletedFile);
  63. PutVarint32(dst, deleted_file_kvp.first); // level
  64. PutVarint64(dst, deleted_file_kvp.second); // file number
  65. }
  66. for (size_t i = 0; i < new_files_.size(); i++) {
  67. const FileMetaData& f = new_files_[i].second;
  68. PutVarint32(dst, kNewFile);
  69. PutVarint32(dst, new_files_[i].first); // level
  70. PutVarint64(dst, f.number);
  71. PutVarint64(dst, f.file_size);
  72. PutLengthPrefixedSlice(dst, f.smallest.Encode());
  73. PutLengthPrefixedSlice(dst, f.largest.Encode());
  74. }
  75. }
  76. static bool GetInternalKey(Slice* input, InternalKey* dst) {
  77. Slice str;
  78. if (GetLengthPrefixedSlice(input, &str)) {
  79. return dst->DecodeFrom(str);
  80. } else {
  81. return false;
  82. }
  83. }
  84. static bool GetLevel(Slice* input, int* level) {
  85. uint32_t v;
  86. if (GetVarint32(input, &v) && v < config::kNumLevels) {
  87. *level = v;
  88. return true;
  89. } else {
  90. return false;
  91. }
  92. }
  93. Status VersionEdit::DecodeFrom(const Slice& src) {
  94. Clear();
  95. Slice input = src;
  96. const char* msg = nullptr;
  97. uint32_t tag;
  98. // Temporary storage for parsing
  99. int level;
  100. uint64_t number;
  101. FileMetaData f;
  102. Slice str;
  103. InternalKey key;
  104. while (msg == nullptr && GetVarint32(&input, &tag)) {
  105. switch (tag) {
  106. case kComparator:
  107. if (GetLengthPrefixedSlice(&input, &str)) {
  108. comparator_ = str.ToString();
  109. has_comparator_ = true;
  110. } else {
  111. msg = "comparator name";
  112. }
  113. break;
  114. case kLogNumber:
  115. if (GetVarint64(&input, &log_number_)) {
  116. has_log_number_ = true;
  117. } else {
  118. msg = "log number";
  119. }
  120. break;
  121. case kPrevLogNumber:
  122. if (GetVarint64(&input, &prev_log_number_)) {
  123. has_prev_log_number_ = true;
  124. } else {
  125. msg = "previous log number";
  126. }
  127. break;
  128. case kNextFileNumber:
  129. if (GetVarint64(&input, &next_file_number_)) {
  130. has_next_file_number_ = true;
  131. } else {
  132. msg = "next file number";
  133. }
  134. break;
  135. case kLastSequence:
  136. if (GetVarint64(&input, &last_sequence_)) {
  137. has_last_sequence_ = true;
  138. } else {
  139. msg = "last sequence number";
  140. }
  141. break;
  142. case kCompactPointer:
  143. if (GetLevel(&input, &level) && GetInternalKey(&input, &key)) {
  144. compact_pointers_.push_back(std::make_pair(level, key));
  145. } else {
  146. msg = "compaction pointer";
  147. }
  148. break;
  149. case kDeletedFile:
  150. if (GetLevel(&input, &level) && GetVarint64(&input, &number)) {
  151. deleted_files_.insert(std::make_pair(level, number));
  152. } else {
  153. msg = "deleted file";
  154. }
  155. break;
  156. case kNewFile:
  157. if (GetLevel(&input, &level) && GetVarint64(&input, &f.number) &&
  158. GetVarint64(&input, &f.file_size) &&
  159. GetInternalKey(&input, &f.smallest) &&
  160. GetInternalKey(&input, &f.largest)) {
  161. new_files_.push_back(std::make_pair(level, f));
  162. } else {
  163. msg = "new-file entry";
  164. }
  165. break;
  166. default:
  167. msg = "unknown tag";
  168. break;
  169. }
  170. }
  171. if (msg == nullptr && !input.empty()) {
  172. msg = "invalid tag";
  173. }
  174. Status result;
  175. if (msg != nullptr) {
  176. result = Status::Corruption("VersionEdit", msg);
  177. }
  178. return result;
  179. }
  180. std::string VersionEdit::DebugString() const {
  181. std::string r;
  182. r.append("VersionEdit {");
  183. if (has_comparator_) {
  184. r.append("\n Comparator: ");
  185. r.append(comparator_);
  186. }
  187. if (has_log_number_) {
  188. r.append("\n LogNumber: ");
  189. AppendNumberTo(&r, log_number_);
  190. }
  191. if (has_prev_log_number_) {
  192. r.append("\n PrevLogNumber: ");
  193. AppendNumberTo(&r, prev_log_number_);
  194. }
  195. if (has_next_file_number_) {
  196. r.append("\n NextFile: ");
  197. AppendNumberTo(&r, next_file_number_);
  198. }
  199. if (has_last_sequence_) {
  200. r.append("\n LastSeq: ");
  201. AppendNumberTo(&r, last_sequence_);
  202. }
  203. for (size_t i = 0; i < compact_pointers_.size(); i++) {
  204. r.append("\n CompactPointer: ");
  205. AppendNumberTo(&r, compact_pointers_[i].first);
  206. r.append(" ");
  207. r.append(compact_pointers_[i].second.DebugString());
  208. }
  209. for (const auto& deleted_files_kvp : deleted_files_) {
  210. r.append("\n DeleteFile: ");
  211. AppendNumberTo(&r, deleted_files_kvp.first);
  212. r.append(" ");
  213. AppendNumberTo(&r, deleted_files_kvp.second);
  214. }
  215. for (size_t i = 0; i < new_files_.size(); i++) {
  216. const FileMetaData& f = new_files_[i].second;
  217. r.append("\n AddFile: ");
  218. AppendNumberTo(&r, new_files_[i].first);
  219. r.append(" ");
  220. AppendNumberTo(&r, f.number);
  221. r.append(" ");
  222. AppendNumberTo(&r, f.file_size);
  223. r.append(" ");
  224. r.append(f.smallest.DebugString());
  225. r.append(" .. ");
  226. r.append(f.largest.DebugString());
  227. }
  228. r.append("\n}\n");
  229. return r;
  230. }
  231. } // namespace leveldb