10225501448 李度 10225101546 陈胤遒 10215501422 高宇菲
Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.
 
 

211 řádky
7.8 KiB

// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. See the AUTHORS file for names of contributors.
#include "db/memtable.h"
#include "db/dbformat.h"
#include "leveldb/comparator.h"
#include "leveldb/env.h"
#include "leveldb/iterator.h"
#include "util/coding.h"
#include "ctime"
#include "iostream"
namespace leveldb {
static Slice GetLengthPrefixedSlice(const char* data) {
uint32_t len;
const char* p = data;
p = GetVarint32Ptr(p, p + 5, &len); // +5: we assume "p" is not corrupted
return Slice(p, len);
}
MemTable::MemTable(const InternalKeyComparator& comparator)
: comparator_(comparator), refs_(0), table_(comparator_, &arena_) {}
MemTable::~MemTable() { assert(refs_ == 0); }
size_t MemTable::ApproximateMemoryUsage() { return arena_.MemoryUsage(); }
int MemTable::KeyComparator::operator()(const char* aptr,
const char* bptr) const {
// Internal keys are encoded as length-prefixed strings.
Slice a = GetLengthPrefixedSlice(aptr);
Slice b = GetLengthPrefixedSlice(bptr);
return comparator.Compare(a, b);
}
// Encode a suitable internal key target for "target" and return it.
// Uses *scratch as scratch space, and the returned pointer will point
// into this scratch space.
static const char* EncodeKey(std::string* scratch, const Slice& target) {
scratch->clear();
PutVarint32(scratch, target.size());
scratch->append(target.data(), target.size());
return scratch->data();
}
class MemTableIterator : public Iterator {
public:
explicit MemTableIterator(MemTable::Table* table) : iter_(table) {}
MemTableIterator(const MemTableIterator&) = delete;
MemTableIterator& operator=(const MemTableIterator&) = delete;
~MemTableIterator() override = default;
bool Valid() const override { return iter_.Valid(); }
void Seek(const Slice& k) override {
iter_.Seek(EncodeKey(&tmp_, k));
MemTable::KeyComparator comp_ = iter_.get_comparator();
while(Valid()) {
Slice now = key();
ParsedInternalKey parsed_k,parsed_now;
ParseInternalKey(k,&parsed_k);
ParseInternalKey(now,&parsed_now);
uint64_t deadtime_k = parsed_k.deadTime;
uint64_t deadtime_now = parsed_now.deadTime;
if(deadtime_k == 0) deadtime_k = UINT64_MAX;
if(deadtime_now == 0) deadtime_now = UINT64_MAX;
if(deadtime_k > deadtime_now) {Next();continue;};
if(comp_.comparator.Compare(k,now) <= 0) return;
Next();
}
}
void SeekToFirst() override { iter_.SeekToFirst(); }
void SeekToLast() override { iter_.SeekToLast(); }
void Next() override { iter_.Next(); }
void Prev() override { iter_.Prev(); }
Slice key() const override { return GetLengthPrefixedSlice(iter_.key()); }
Slice value() const override {
Slice key_slice = GetLengthPrefixedSlice(iter_.key());
return GetLengthPrefixedSlice(key_slice.data() + key_slice.size());
}
Status status() const override { return Status::OK(); }
private:
MemTable::Table::Iterator iter_;
std::string tmp_; // For passing to EncodeKey
};
Iterator* MemTable::NewIterator() { return new MemTableIterator(&table_); }
void MemTable::Add(SequenceNumber s, ValueType type, const Slice& key,
const Slice& value, uint64_t deadTime) {
// Format of an entry is concatenation of:
// key_size : varint32 of internal_key.size()
// key bytes : char[internal_key.size()]
// tag : uint64((sequence << 8) | type)
// value_size : varint32 of value.size()
// value bytes : char[value.size()]
//变成
// key_size : varint32 of internal_key.size()
// key bytes : char[internal_key.size()]
// (deadTime) : uint64(可能有)
// tag : uint64((sequence << 8) | havettl << 1 | type)
// value_size : varint32 of value.size()
// value bytes : char[value.size()]
size_t key_size = key.size();
size_t val_size = value.size();
size_t internal_key_size = key_size + 8;
if(deadTime != 0) internal_key_size += 8;
const size_t encoded_len = VarintLength(internal_key_size) +
internal_key_size + VarintLength(val_size) +
val_size;
char* buf = arena_.Allocate(encoded_len);
char* p = EncodeVarint32(buf, internal_key_size);
std::memcpy(p, key.data(), key_size);
p += key_size;
if(deadTime == 0){
EncodeFixed64(p, (s << 8) | type);
} else {
EncodeFixed64(p, deadTime);
p += 8;
EncodeFixed64(p, (s << 8) | 0b10 | type);
}
p += 8;
p = EncodeVarint32(p, val_size);
std::memcpy(p, value.data(), val_size);
assert(p + val_size == buf + encoded_len);
table_.Insert(buf);
static int count = 0;
if(count++ % 1000 == 0)
std::cout<<"count: "<<count << " insert:" << key.ToString() <<" deadTime: " << deadTime << std::endl;
}
bool MemTable::Get(const LookupKey& key, std::string* value, Status* s) {
Slice memkey = key.memtable_key();
Table::Iterator iter(&table_);
iter.Seek(memkey.data());
while(iter.Valid()) {
Slice now = GetLengthPrefixedSlice(iter.key()); //迭代器所处的位置
MemTable::KeyComparator comp_ = iter.get_comparator();
ParsedInternalKey parsed_k,parsed_now;
ParseInternalKey(key.internal_key(),&parsed_k);
ParseInternalKey(now,&parsed_now);
uint64_t deadtime_k = parsed_k.deadTime;
uint64_t deadtime_now = parsed_now.deadTime;
if(deadtime_k == 0) deadtime_k = UINT64_MAX;
if(deadtime_now == 0) deadtime_now = UINT64_MAX;
std::cout<<"key :"<<parsed_k.user_key.ToString()<<" k time: "<<deadtime_k<<" now time: "<<deadtime_now<<std::endl;
std::cout<<"k&now"<<parsed_k.user_key.ToString()<<" "<<parsed_now.user_key.ToString()<<std::endl;
if(deadtime_k > deadtime_now) {
iter.Next();
continue;
}
std::cout<<"size : "<<key.internal_key().size()<<" "<<now.size()<<std::endl;
if(comp_.comparator.Compare(key.internal_key(),now) <= 0) break;
iter.Next();
}
std::cout << "search:" << key.user_key().ToString() << " valid?" << iter.Valid();
if (iter.Valid()) {
// entry format is:
// klength varint32
// userkey char[klength]
// (deadTime) uint64
// tag uint64
// vlength varint32
// value char[vlength]
// Check that it belongs to same user key. We do not check the
// sequence number since the Seek() call above should have skipped
// all entries with overly large sequence numbers.
const char* entry = iter.key();
uint32_t key_length;
const char* key_ptr = GetVarint32Ptr(entry, entry + 5, &key_length);
std::cout << " get:" << ExtractUserKey(Slice(key_ptr, key_length)).ToString() << std::endl;
if (comparator_.comparator.user_comparator()->Compare(
ExtractUserKey(Slice(key_ptr, key_length)), key.user_key()) == 0) {
// Correct user key
const uint64_t tag = DecodeFixed64(key_ptr + key_length - 8);
switch (static_cast<ValueType>(tag & 0x01)) {
case kTypeValue: {
// uint8_t havettl = (tag & 0xff) >> 1;
// if(havettl){
// time_t nowTime;
// time(&nowTime);
// assert(nowTime > 0);
// const uint64_t deadTime = DecodeFixed64(key_ptr + key_length - 16);
// if(static_cast<uint64_t>(nowTime) >= deadTime){ //过期了
// std::cout << nowTime << "dead:" << deadTime << std::endl;
// *s = Status::NotFound(Slice());
// return true; //todo:之前有没过期的key
// }
// }
Slice v = GetLengthPrefixedSlice(key_ptr + key_length);
value->assign(v.data(), v.size());
return true;
}
case kTypeDeletion:
*s = Status::NotFound(Slice());
return true;
}
}
}
return false;
}
} // namespace leveldb