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.

282 lines
7.5 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. kLargeValueRef = 8,
  19. };
  20. void VersionEdit::Clear() {
  21. comparator_.clear();
  22. log_number_ = 0;
  23. last_sequence_ = 0;
  24. next_file_number_ = 0;
  25. has_comparator_ = false;
  26. has_log_number_ = false;
  27. has_next_file_number_ = false;
  28. has_last_sequence_ = false;
  29. deleted_files_.clear();
  30. new_files_.clear();
  31. large_refs_added_.clear();
  32. }
  33. void VersionEdit::EncodeTo(std::string* dst) const {
  34. if (has_comparator_) {
  35. PutVarint32(dst, kComparator);
  36. PutLengthPrefixedSlice(dst, comparator_);
  37. }
  38. if (has_log_number_) {
  39. PutVarint32(dst, kLogNumber);
  40. PutVarint64(dst, log_number_);
  41. }
  42. if (has_next_file_number_) {
  43. PutVarint32(dst, kNextFileNumber);
  44. PutVarint64(dst, next_file_number_);
  45. }
  46. if (has_last_sequence_) {
  47. PutVarint32(dst, kLastSequence);
  48. PutVarint64(dst, last_sequence_);
  49. }
  50. for (int i = 0; i < compact_pointers_.size(); i++) {
  51. PutVarint32(dst, kCompactPointer);
  52. PutVarint32(dst, compact_pointers_[i].first); // level
  53. PutLengthPrefixedSlice(dst, compact_pointers_[i].second.Encode());
  54. }
  55. for (DeletedFileSet::const_iterator iter = deleted_files_.begin();
  56. iter != deleted_files_.end();
  57. ++iter) {
  58. PutVarint32(dst, kDeletedFile);
  59. PutVarint32(dst, iter->first); // level
  60. PutVarint64(dst, iter->second); // file number
  61. }
  62. for (int i = 0; i < new_files_.size(); i++) {
  63. const FileMetaData& f = new_files_[i].second;
  64. PutVarint32(dst, kNewFile);
  65. PutVarint32(dst, new_files_[i].first); // level
  66. PutVarint64(dst, f.number);
  67. PutVarint64(dst, f.file_size);
  68. PutLengthPrefixedSlice(dst, f.smallest.Encode());
  69. PutLengthPrefixedSlice(dst, f.largest.Encode());
  70. }
  71. for (int i = 0; i < large_refs_added_.size(); i++) {
  72. const VersionEdit::Large& l = large_refs_added_[i];
  73. PutVarint32(dst, kLargeValueRef);
  74. PutLengthPrefixedSlice(dst,
  75. Slice(l.large_ref.data, LargeValueRef::ByteSize()));
  76. PutVarint64(dst, l.fnum);
  77. PutLengthPrefixedSlice(dst, l.internal_key.Encode());
  78. }
  79. }
  80. static bool GetInternalKey(Slice* input, InternalKey* dst) {
  81. Slice str;
  82. if (GetLengthPrefixedSlice(input, &str)) {
  83. dst->DecodeFrom(str);
  84. return true;
  85. } else {
  86. return false;
  87. }
  88. }
  89. static bool GetLevel(Slice* input, int* level) {
  90. uint32_t v;
  91. if (GetVarint32(input, &v) &&
  92. v < config::kNumLevels) {
  93. *level = v;
  94. return true;
  95. } else {
  96. return false;
  97. }
  98. }
  99. Status VersionEdit::DecodeFrom(const Slice& src) {
  100. Clear();
  101. Slice input = src;
  102. const char* msg = NULL;
  103. uint32_t tag;
  104. // Temporary storage for parsing
  105. int level;
  106. uint64_t number;
  107. FileMetaData f;
  108. Slice str;
  109. Large large;
  110. InternalKey key;
  111. while (msg == NULL && GetVarint32(&input, &tag)) {
  112. switch (tag) {
  113. case kComparator:
  114. if (GetLengthPrefixedSlice(&input, &str)) {
  115. comparator_ = str.ToString();
  116. has_comparator_ = true;
  117. } else {
  118. msg = "comparator name";
  119. }
  120. break;
  121. case kLogNumber:
  122. if (GetVarint64(&input, &log_number_)) {
  123. has_log_number_ = true;
  124. } else {
  125. msg = "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) &&
  144. GetInternalKey(&input, &key)) {
  145. compact_pointers_.push_back(std::make_pair(level, key));
  146. } else {
  147. msg = "compaction pointer";
  148. }
  149. break;
  150. case kDeletedFile:
  151. if (GetLevel(&input, &level) &&
  152. GetVarint64(&input, &number)) {
  153. deleted_files_.insert(std::make_pair(level, number));
  154. } else {
  155. msg = "deleted file";
  156. }
  157. break;
  158. case kNewFile:
  159. if (GetLevel(&input, &level) &&
  160. GetVarint64(&input, &f.number) &&
  161. GetVarint64(&input, &f.file_size) &&
  162. GetInternalKey(&input, &f.smallest) &&
  163. GetInternalKey(&input, &f.largest)) {
  164. new_files_.push_back(std::make_pair(level, f));
  165. } else {
  166. msg = "new-file entry";
  167. }
  168. break;
  169. case kLargeValueRef:
  170. if (GetLengthPrefixedSlice(&input, &str) &&
  171. (str.size() == LargeValueRef::ByteSize()) &&
  172. GetVarint64(&input, &large.fnum) &&
  173. GetInternalKey(&input, &large.internal_key)) {
  174. large.large_ref = LargeValueRef::FromRef(str);
  175. large_refs_added_.push_back(large);
  176. } else {
  177. msg = "large ref";
  178. }
  179. break;
  180. default:
  181. msg = "unknown tag";
  182. break;
  183. }
  184. }
  185. if (msg == NULL && !input.empty()) {
  186. msg = "invalid tag";
  187. }
  188. Status result;
  189. if (msg != NULL) {
  190. result = Status::Corruption("VersionEdit", msg);
  191. }
  192. return result;
  193. }
  194. std::string VersionEdit::DebugString() const {
  195. std::string r;
  196. r.append("VersionEdit {");
  197. if (has_comparator_) {
  198. r.append("\n Comparator: ");
  199. r.append(comparator_);
  200. }
  201. if (has_log_number_) {
  202. r.append("\n LogNumber: ");
  203. AppendNumberTo(&r, log_number_);
  204. }
  205. if (has_next_file_number_) {
  206. r.append("\n NextFile: ");
  207. AppendNumberTo(&r, next_file_number_);
  208. }
  209. if (has_last_sequence_) {
  210. r.append("\n LastSeq: ");
  211. AppendNumberTo(&r, last_sequence_);
  212. }
  213. for (int i = 0; i < compact_pointers_.size(); i++) {
  214. r.append("\n CompactPointer: ");
  215. AppendNumberTo(&r, compact_pointers_[i].first);
  216. r.append(" '");
  217. AppendEscapedStringTo(&r, compact_pointers_[i].second.Encode());
  218. r.append("'");
  219. }
  220. for (DeletedFileSet::const_iterator iter = deleted_files_.begin();
  221. iter != deleted_files_.end();
  222. ++iter) {
  223. r.append("\n DeleteFile: ");
  224. AppendNumberTo(&r, iter->first);
  225. r.append(" ");
  226. AppendNumberTo(&r, iter->second);
  227. }
  228. for (int i = 0; i < new_files_.size(); i++) {
  229. const FileMetaData& f = new_files_[i].second;
  230. r.append("\n AddFile: ");
  231. AppendNumberTo(&r, new_files_[i].first);
  232. r.append(" ");
  233. AppendNumberTo(&r, f.number);
  234. r.append(" ");
  235. AppendNumberTo(&r, f.file_size);
  236. r.append(" '");
  237. AppendEscapedStringTo(&r, f.smallest.Encode());
  238. r.append("' .. '");
  239. AppendEscapedStringTo(&r, f.largest.Encode());
  240. r.append("'");
  241. }
  242. for (int i = 0; i < large_refs_added_.size(); i++) {
  243. const VersionEdit::Large& l = large_refs_added_[i];
  244. r.append("\n LargeRef: ");
  245. AppendNumberTo(&r, l.fnum);
  246. r.append(" ");
  247. r.append(LargeValueRefToFilenameString(l.large_ref));
  248. r.append(" '");
  249. AppendEscapedStringTo(&r, l.internal_key.Encode());
  250. r.append("'");
  251. }
  252. r.append("\n}\n");
  253. return r;
  254. }
  255. }