~ubuntu-branches/ubuntu/quantal/ceph/quantal

« back to all changes in this revision

Viewing changes to src/leveldb/table/format.cc

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2012-07-16 09:56:24 UTC
  • mfrom: (0.3.11)
  • mto: This revision was merged to the branch mainline in revision 17.
  • Revision ID: package-import@ubuntu.com-20120716095624-azr2w4hbhei1rxmx
Tags: upstream-0.48
ImportĀ upstreamĀ versionĀ 0.48

Show diffs side-by-side

added added

removed removed

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