作者: 韩晨旭 10225101440 李畅 10225102463
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

135 строки
4.1 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 "table/format.h"
  5. #include "leveldb/env.h"
  6. #include "port/port.h"
  7. #include "table/block.h"
  8. #include "util/coding.h"
  9. #include "util/crc32c.h"
  10. namespace leveldb {
  11. void BlockHandle::EncodeTo(std::string* dst) const {
  12. // Sanity check that all fields have been set
  13. assert(offset_ != ~static_cast<uint64_t>(0));
  14. assert(size_ != ~static_cast<uint64_t>(0));
  15. PutVarint64(dst, offset_);
  16. PutVarint64(dst, size_);
  17. }
  18. Status BlockHandle::DecodeFrom(Slice* input) {
  19. if (GetVarint64(input, &offset_) &&
  20. GetVarint64(input, &size_)) {
  21. return Status::OK();
  22. } else {
  23. return Status::Corruption("bad block handle");
  24. }
  25. }
  26. void Footer::EncodeTo(std::string* dst) const {
  27. #ifndef NDEBUG
  28. const size_t original_size = dst->size();
  29. #endif
  30. metaindex_handle_.EncodeTo(dst);
  31. index_handle_.EncodeTo(dst);
  32. dst->resize(2 * BlockHandle::kMaxEncodedLength); // Padding
  33. PutFixed32(dst, static_cast<uint32_t>(kTableMagicNumber & 0xffffffffu));
  34. PutFixed32(dst, static_cast<uint32_t>(kTableMagicNumber >> 32));
  35. assert(dst->size() == original_size + kEncodedLength);
  36. }
  37. Status Footer::DecodeFrom(Slice* input) {
  38. const char* magic_ptr = input->data() + kEncodedLength - 8;
  39. const uint32_t magic_lo = DecodeFixed32(magic_ptr);
  40. const uint32_t magic_hi = DecodeFixed32(magic_ptr + 4);
  41. const uint64_t magic = ((static_cast<uint64_t>(magic_hi) << 32) |
  42. (static_cast<uint64_t>(magic_lo)));
  43. if (magic != kTableMagicNumber) {
  44. return Status::InvalidArgument("not an sstable (bad magic number)");
  45. }
  46. Status result = metaindex_handle_.DecodeFrom(input);
  47. if (result.ok()) {
  48. result = index_handle_.DecodeFrom(input);
  49. }
  50. if (result.ok()) {
  51. // We skip over any leftover data (just padding for now) in "input"
  52. const char* end = magic_ptr + 8;
  53. *input = Slice(end, input->data() + input->size() - end);
  54. }
  55. return result;
  56. }
  57. Status ReadBlock(RandomAccessFile* file,
  58. const ReadOptions& options,
  59. const BlockHandle& handle,
  60. Block** block) {
  61. *block = NULL;
  62. // Read the block contents as well as the type/crc footer.
  63. // See table_builder.cc for the code that built this structure.
  64. size_t n = static_cast<size_t>(handle.size());
  65. char* buf = new char[n + kBlockTrailerSize];
  66. Slice contents;
  67. Status s = file->Read(handle.offset(), n + kBlockTrailerSize, &contents, buf);
  68. if (!s.ok()) {
  69. delete[] buf;
  70. return s;
  71. }
  72. if (contents.size() != n + kBlockTrailerSize) {
  73. delete[] buf;
  74. return Status::Corruption("truncated block read");
  75. }
  76. // Check the crc of the type and the block contents
  77. const char* data = contents.data(); // Pointer to where Read put the data
  78. if (options.verify_checksums) {
  79. const uint32_t crc = crc32c::Unmask(DecodeFixed32(data + n + 1));
  80. const uint32_t actual = crc32c::Value(data, n + 1);
  81. if (actual != crc) {
  82. delete[] buf;
  83. s = Status::Corruption("block checksum mismatch");
  84. return s;
  85. }
  86. }
  87. switch (data[n]) {
  88. case kNoCompression:
  89. if (data != buf) {
  90. // File implementation gave us pointer to some other data.
  91. // Copy into buf[].
  92. memcpy(buf, data, n + kBlockTrailerSize);
  93. }
  94. // Ok
  95. break;
  96. case kSnappyCompression: {
  97. size_t ulength = 0;
  98. if (!port::Snappy_GetUncompressedLength(data, n, &ulength)) {
  99. delete[] buf;
  100. return Status::Corruption("corrupted compressed block contents");
  101. }
  102. char* ubuf = new char[ulength];
  103. if (!port::Snappy_Uncompress(data, n, ubuf)) {
  104. delete[] buf;
  105. delete[] ubuf;
  106. return Status::Corruption("corrupted compressed block contents");
  107. }
  108. delete[] buf;
  109. buf = ubuf;
  110. n = ulength;
  111. break;
  112. }
  113. default:
  114. delete[] buf;
  115. return Status::Corruption("bad block type");
  116. }
  117. *block = new Block(buf, n); // Block takes ownership of buf[]
  118. return Status::OK();
  119. }
  120. }