~ubuntu-branches/debian/jessie/armory/jessie

« back to all changes in this revision

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

  • Committer: Package Import Robot
  • Author(s): Joseph Bisch
  • Date: 2014-10-07 10:22:45 UTC
  • Revision ID: package-import@ubuntu.com-20141007102245-2s3x3rhjxg689hek
Tags: upstream-0.92.3
ImportĀ upstreamĀ versionĀ 0.92.3

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
                 BlockContents* result) {
 
70
  result->data = Slice();
 
71
  result->cachable = false;
 
72
  result->heap_allocated = false;
 
73
 
 
74
  // Read the block contents as well as the type/crc footer.
 
75
  // See table_builder.cc for the code that built this structure.
 
76
  size_t n = static_cast<size_t>(handle.size());
 
77
  char* buf = new char[n + kBlockTrailerSize];
 
78
  Slice contents;
 
79
  Status s = file->Read(handle.offset(), n + kBlockTrailerSize, &contents, buf);
 
80
  if (!s.ok()) {
 
81
    delete[] buf;
 
82
    return s;
 
83
  }
 
84
  if (contents.size() != n + kBlockTrailerSize) {
 
85
    delete[] buf;
 
86
    return Status::Corruption("truncated block read");
 
87
  }
 
88
 
 
89
  // Check the crc of the type and the block contents
 
90
  const char* data = contents.data();    // Pointer to where Read put the data
 
91
  if (options.verify_checksums) {
 
92
    const uint32_t crc = crc32c::Unmask(DecodeFixed32(data + n + 1));
 
93
    const uint32_t actual = crc32c::Value(data, n + 1);
 
94
    if (actual != crc) {
 
95
      delete[] buf;
 
96
      s = Status::Corruption("block checksum mismatch");
 
97
      return s;
 
98
    }
 
99
  }
 
100
 
 
101
  switch (data[n]) {
 
102
    case kNoCompression:
 
103
      if (data != buf) {
 
104
        // File implementation gave us pointer to some other data.
 
105
        // Use it directly under the assumption that it will be live
 
106
        // while the file is open.
 
107
        delete[] buf;
 
108
        result->data = Slice(data, n);
 
109
        result->heap_allocated = false;
 
110
        result->cachable = false;  // Do not double-cache
 
111
      } else {
 
112
        result->data = Slice(buf, n);
 
113
        result->heap_allocated = true;
 
114
        result->cachable = true;
 
115
      }
 
116
 
 
117
      // Ok
 
118
      break;
 
119
    case kSnappyCompression: {
 
120
      size_t ulength = 0;
 
121
      if (!port::Snappy_GetUncompressedLength(data, n, &ulength)) {
 
122
        delete[] buf;
 
123
        return Status::Corruption("corrupted compressed block contents");
 
124
      }
 
125
      char* ubuf = new char[ulength];
 
126
      if (!port::Snappy_Uncompress(data, n, ubuf)) {
 
127
        delete[] buf;
 
128
        delete[] ubuf;
 
129
        return Status::Corruption("corrupted compressed block contents");
 
130
      }
 
131
      delete[] buf;
 
132
      result->data = Slice(ubuf, ulength);
 
133
      result->heap_allocated = true;
 
134
      result->cachable = true;
 
135
      break;
 
136
    }
 
137
    default:
 
138
      delete[] buf;
 
139
      return Status::Corruption("bad block type");
 
140
  }
 
141
 
 
142
  return Status::OK();
 
143
}
 
144
 
 
145
}  // namespace leveldb