Skip to content

Commit 9730044

Browse files
committed
feat(sstable): add partial format definition
1 parent 61ec566 commit 9730044

2 files changed

Lines changed: 193 additions & 0 deletions

File tree

src/table/format.cc

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
#include "format.h"
2+
3+
#include <sys/types.h>
4+
5+
#include <cassert>
6+
#include <cstddef>
7+
#include <cstdint>
8+
9+
#include "status.h"
10+
#include "util/coding.h"
11+
12+
namespace db {
13+
14+
void BlockHandle::EncodeTo(std::string* dst) const {
15+
assert(offset_ != ~static_cast<u_int64_t>(0));
16+
assert(size_ != ~static_cast<u_int64_t>(0));
17+
PutVarint64(dst, offset_);
18+
PutVarint64(dst, size_);
19+
}
20+
21+
Status BlockHandle::DecodeFrom(Slice* input) {
22+
if (GetVarint64(input, &offset_) && GetVarint64(input, &size_)) {
23+
return Status::OkStatus();
24+
} else {
25+
return Status::Corruption("bad block handle");
26+
}
27+
}
28+
29+
void Footer::EncodeTo(std::string* dst) const {
30+
const size_t original_size = dst->size();
31+
metaindex_handle_.EncodeTo(dst);
32+
index_handle_.EncodeTo(dst);
33+
dst->resize(2 * BlockHandle::kMaxEncodedLength); // padding
34+
PutFixed32(dst, static_cast<uint32_t>(kTableMagicNumber) & 0xffffffffu);
35+
PutFixed32(dst, static_cast<uint32_t>(kTableMagicNumber >> 32));
36+
assert(dst->size() == original_size + kEncodeLenght);
37+
(void)original_size;
38+
}
39+
40+
Status Footer::DecodeFrom(Slice* input) {
41+
if (input->Size() < kEncodeLenght) {
42+
return Status::Corruption("not an sstable (footer too short)");
43+
}
44+
45+
const char* magic_ptr = input->Data() + kEncodeLenght - 8;
46+
const uint32_t magic_lo = DecodeFixed32(magic_ptr);
47+
const uint32_t magic_hi = DecodeFixed32(magic_ptr + 4);
48+
const u_int64_t magic =
49+
((static_cast<u_int64_t>(magic_hi) << 32) | (static_cast<u_int64_t>(magic_lo)));
50+
// magic num judge if the file valid
51+
if (magic != kTableMagicNumber) {
52+
return Status::Corruption("not an sstable (bad magic number)");
53+
}
54+
55+
Status result = metaindex_handle_.DecodeFrom(input);
56+
if (result.Ok()) {
57+
result = index_handle_.DecodeFrom(input);
58+
}
59+
if (result.Ok()) {
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, const ReadOptions& options, const BlockHandle& handle,
67+
BlockContents* result) {
68+
// TODO:
69+
// 1. implement env.h
70+
// 2. implement this method
71+
return Status::OkStatus();
72+
}
73+
74+
} // namespace db

src/table/format.h

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
#include <sys/types.h>
2+
3+
#include <cstddef>
4+
#include <string>
5+
6+
#include "status.h"
7+
namespace db {
8+
class Block;
9+
class RandomAccessFile;
10+
struct ReadOptions;
11+
12+
// SSTable Format
13+
//
14+
// +------------------+
15+
// | Data Blocks |
16+
// +------------------+
17+
// | Filter Block ? |
18+
// +------------------+
19+
// | Metaindex Block |
20+
// +------------------+
21+
// | Index Block |
22+
// +------------------+
23+
// | Footer |
24+
// +------------------+
25+
//
26+
// The Filter Block is optional.
27+
28+
// descripe a block 's position and size
29+
// BlockHanlde's max size is 10
30+
class BlockHandle {
31+
public:
32+
enum { kMaxEncodedLength = 10 + 10 };
33+
34+
BlockHandle();
35+
36+
u_int64_t offset() const {
37+
return offset_;
38+
}
39+
void set_offset(u_int64_t offset) {
40+
offset_ = offset;
41+
}
42+
43+
u_int64_t size() const {
44+
return size_;
45+
}
46+
void set_size(u_int64_t size) {
47+
size_ = size;
48+
}
49+
50+
void EncodeTo(std::string* dst) const;
51+
Status DecodeFrom(Slice* input);
52+
53+
private:
54+
u_int64_t offset_;
55+
u_int64_t size_;
56+
};
57+
58+
// Footer Format:
59+
//
60+
// [ meta BlockHandle ]
61+
// [ index BlockHandle ]
62+
// [ empty ]
63+
// [ magic num ]
64+
//
65+
// Note: Unused bytes in meta/index BlockHandle are left empty to keep Footer size fixed.
66+
// Footer has a Fixed Size 48
67+
class Footer {
68+
public:
69+
// two of BlockHandle: index_handle and metaindex_hanle
70+
// 8 is the size of MagicNum
71+
enum { kEncodeLenght = 2 * BlockHandle::kMaxEncodedLength + 8 };
72+
73+
Footer() = default;
74+
75+
const BlockHandle& metaindex_handle() const {
76+
return metaindex_handle_;
77+
}
78+
void set_metaindex_handle(const BlockHandle& h) {
79+
metaindex_handle_ = h;
80+
}
81+
82+
const BlockHandle& index_handle() const {
83+
return index_handle_;
84+
}
85+
void set_index_handle(const BlockHandle& h) {
86+
index_handle_ = h;
87+
}
88+
89+
void EncodeTo(std::string* dst) const;
90+
Status DecodeFrom(Slice* input);
91+
92+
private:
93+
BlockHandle metaindex_handle_;
94+
BlockHandle index_handle_;
95+
};
96+
97+
// https://github.com/aetherance/db | sha1sum
98+
//
99+
// This magic num will be written into Footer by Footer::EncodeTo()
100+
// And will be used to judge if the footer is correct
101+
static const u_int64_t kTableMagicNumber = 0x8c7f4e0c9d6a2b31ull;
102+
103+
// tail after block
104+
static const size_t kBlockTrailerSize = 5;
105+
106+
// Block Readed into memory
107+
struct BlockContents {
108+
Slice data;
109+
bool cachable;
110+
bool heep_allocated;
111+
};
112+
113+
// offset_ = size_ = UINT64_MAX;
114+
Status ReadBlock(RandomAccessFile* file, const ReadOptions& options, const BlockHandle& handle,
115+
BlockContents* result);
116+
117+
inline BlockHandle::BlockHandle()
118+
: offset_(~static_cast<u_int64_t>(0)), size_(~static_cast<u_int64_t>(0)) {}
119+
} // namespace db

0 commit comments

Comments
 (0)