Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

266 рядки
6.8 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 (DeletedFileSet::const_iterator iter = deleted_files_.begin();
  62. iter != deleted_files_.end();
  63. ++iter) {
  64. PutVarint32(dst, kDeletedFile);
  65. PutVarint32(dst, iter->first); // level
  66. PutVarint64(dst, iter->second); // file number
  67. }
  68. for (size_t i = 0; i < new_files_.size(); i++) {
  69. const FileMetaData& f = new_files_[i].second;
  70. PutVarint32(dst, kNewFile);
  71. PutVarint32(dst, new_files_[i].first); // level
  72. PutVarint64(dst, f.number);
  73. PutVarint64(dst, f.file_size);
  74. PutLengthPrefixedSlice(dst, f.smallest.Encode());
  75. PutLengthPrefixedSlice(dst, f.largest.Encode());
  76. }
  77. }
  78. static bool GetInternalKey(Slice* input, InternalKey* dst) {
  79. Slice str;
  80. if (GetLengthPrefixedSlice(input, &str)) {
  81. dst->DecodeFrom(str);
  82. return true;
  83. } else {
  84. return false;
  85. }
  86. }
  87. static bool GetLevel(Slice* input, int* level) {
  88. uint32_t v;
  89. if (GetVarint32(input, &v) &&
  90. v < config::kNumLevels) {
  91. *level = v;
  92. return true;
  93. } else {
  94. return false;
  95. }
  96. }
  97. Status VersionEdit::DecodeFrom(const Slice& src) {
  98. Clear();
  99. Slice input = src;
  100. const char* msg = nullptr;
  101. uint32_t tag;
  102. // Temporary storage for parsing
  103. int level;
  104. uint64_t number;
  105. FileMetaData f;
  106. Slice str;
  107. InternalKey key;
  108. while (msg == nullptr && GetVarint32(&input, &tag)) {
  109. switch (tag) {
  110. case kComparator:
  111. if (GetLengthPrefixedSlice(&input, &str)) {
  112. comparator_ = str.ToString();
  113. has_comparator_ = true;
  114. } else {
  115. msg = "comparator name";
  116. }
  117. break;
  118. case kLogNumber:
  119. if (GetVarint64(&input, &log_number_)) {
  120. has_log_number_ = true;
  121. } else {
  122. msg = "log number";
  123. }
  124. break;
  125. case kPrevLogNumber:
  126. if (GetVarint64(&input, &prev_log_number_)) {
  127. has_prev_log_number_ = true;
  128. } else {
  129. msg = "previous log number";
  130. }
  131. break;
  132. case kNextFileNumber:
  133. if (GetVarint64(&input, &next_file_number_)) {
  134. has_next_file_number_ = true;
  135. } else {
  136. msg = "next file number";
  137. }
  138. break;
  139. case kLastSequence:
  140. if (GetVarint64(&input, &last_sequence_)) {
  141. has_last_sequence_ = true;
  142. } else {
  143. msg = "last sequence number";
  144. }
  145. break;
  146. case kCompactPointer:
  147. if (GetLevel(&input, &level) &&
  148. GetInternalKey(&input, &key)) {
  149. compact_pointers_.push_back(std::make_pair(level, key));
  150. } else {
  151. msg = "compaction pointer";
  152. }
  153. break;
  154. case kDeletedFile:
  155. if (GetLevel(&input, &level) &&
  156. GetVarint64(&input, &number)) {
  157. deleted_files_.insert(std::make_pair(level, number));
  158. } else {
  159. msg = "deleted file";
  160. }
  161. break;
  162. case kNewFile:
  163. if (GetLevel(&input, &level) &&
  164. GetVarint64(&input, &f.number) &&
  165. GetVarint64(&input, &f.file_size) &&
  166. GetInternalKey(&input, &f.smallest) &&
  167. GetInternalKey(&input, &f.largest)) {
  168. new_files_.push_back(std::make_pair(level, f));
  169. } else {
  170. msg = "new-file entry";
  171. }
  172. break;
  173. default:
  174. msg = "unknown tag";
  175. break;
  176. }
  177. }
  178. if (msg == nullptr && !input.empty()) {
  179. msg = "invalid tag";
  180. }
  181. Status result;
  182. if (msg != nullptr) {
  183. result = Status::Corruption("VersionEdit", msg);
  184. }
  185. return result;
  186. }
  187. std::string VersionEdit::DebugString() const {
  188. std::string r;
  189. r.append("VersionEdit {");
  190. if (has_comparator_) {
  191. r.append("\n Comparator: ");
  192. r.append(comparator_);
  193. }
  194. if (has_log_number_) {
  195. r.append("\n LogNumber: ");
  196. AppendNumberTo(&r, log_number_);
  197. }
  198. if (has_prev_log_number_) {
  199. r.append("\n PrevLogNumber: ");
  200. AppendNumberTo(&r, prev_log_number_);
  201. }
  202. if (has_next_file_number_) {
  203. r.append("\n NextFile: ");
  204. AppendNumberTo(&r, next_file_number_);
  205. }
  206. if (has_last_sequence_) {
  207. r.append("\n LastSeq: ");
  208. AppendNumberTo(&r, last_sequence_);
  209. }
  210. for (size_t i = 0; i < compact_pointers_.size(); i++) {
  211. r.append("\n CompactPointer: ");
  212. AppendNumberTo(&r, compact_pointers_[i].first);
  213. r.append(" ");
  214. r.append(compact_pointers_[i].second.DebugString());
  215. }
  216. for (DeletedFileSet::const_iterator iter = deleted_files_.begin();
  217. iter != deleted_files_.end();
  218. ++iter) {
  219. r.append("\n DeleteFile: ");
  220. AppendNumberTo(&r, iter->first);
  221. r.append(" ");
  222. AppendNumberTo(&r, iter->second);
  223. }
  224. for (size_t i = 0; i < new_files_.size(); i++) {
  225. const FileMetaData& f = new_files_[i].second;
  226. r.append("\n AddFile: ");
  227. AppendNumberTo(&r, new_files_[i].first);
  228. r.append(" ");
  229. AppendNumberTo(&r, f.number);
  230. r.append(" ");
  231. AppendNumberTo(&r, f.file_size);
  232. r.append(" ");
  233. r.append(f.smallest.DebugString());
  234. r.append(" .. ");
  235. r.append(f.largest.DebugString());
  236. }
  237. r.append("\n}\n");
  238. return r;
  239. }
  240. } // namespace leveldb