Sfoglia il codice sorgente

Merge commit '7575417f53d028dc0b50853bbc530ad28533d7dd' into cyq

pull/1/head
cyq 3 settimane fa
parent
commit
8427741b4c
14 ha cambiato i file con 166 aggiunte e 47 eliminazioni
  1. +1
    -0
      CMakeLists.txt
  2. +11
    -0
      db/builder.cc
  3. +39
    -2
      db/db_impl.cc
  4. +1
    -0
      db/db_impl.h
  5. +3
    -3
      db/db_test.cc
  6. +12
    -11
      db/dbformat.cc
  7. +5
    -1
      db/dbformat.h
  8. +40
    -2
      db/memtable.cc
  9. +2
    -0
      db/skiplist.h
  10. +3
    -0
      db/version_set.cc
  11. +2
    -0
      db/version_set.h
  12. +11
    -0
      table/block.cc
  13. +4
    -4
      test/ttl_mmtable_test.cc
  14. +32
    -24
      test/ttl_test.cc

+ 1
- 0
CMakeLists.txt Vedi File

@ -107,6 +107,7 @@ configure_file(
include_directories(
"${PROJECT_BINARY_DIR}/include"
"."
"./third_party/googletest/googletest/include/"
)
if(BUILD_SHARED_LIBS)

+ 11
- 0
db/builder.cc Vedi File

@ -28,6 +28,10 @@ Status BuildTable(const std::string& dbname, Env* env, const Options& options,
return s;
}
time_t nowTime;
time(&nowTime);
assert(nowTime > 0);
TableBuilder* builder = new TableBuilder(options, file);
meta->smallest.DecodeFrom(iter->key());
Slice key;
@ -41,6 +45,13 @@ Status BuildTable(const std::string& dbname, Env* env, const Options& options,
//这里要注意internalkey和metadata中对于没有生存期的表示的转换
ParseInternalKey(key,&parsed);
if(parsed.deadTime == 0) parsed.deadTime = UINT64_MAX;
if(parsed.deadTime < nowTime) {
static int count = 0;
if(count % 1000 == 0) {
std::cout<<"count "<<count++<<" drop dead in L0: "<<parsed.user_key.ToString()<<" "<<parsed.deadTime<<std::endl;
}
continue;
}
meta->smallest_deadtime = std::min(meta->smallest_deadtime,parsed.deadTime);
meta->largest_deadtime = std::max(meta->largest_deadtime,parsed.deadTime);
}

+ 39
- 2
db/db_impl.cc Vedi File

@ -591,6 +591,7 @@ void DBImpl::CompactRange(const Slice* begin, const Slice* end) {
}
}
}
// max_level_with_files = config::kNumLevels - 1; //TODO:强制合并所有level中的sst,但是这么做不是很优雅
TEST_CompactMemTable(); // TODO(sanjay): Skip if memtable does not overlap
for (int level = 0; level < max_level_with_files; level++) {
TEST_CompactRange(level, begin, end);
@ -705,6 +706,31 @@ void DBImpl::BackgroundCall() {
background_work_finished_signal_.SignalAll();
}
bool DBImpl::RemoveExpireTable() {
bool remove = false;
VersionEdit edit;
time_t nowTime;
time(&nowTime);
Version *base = versions_->current();
base->Ref();
for(int level = 0; level < config::kNumLevels; level ++) {
const std::vector<FileMetaData*> &files = versions_->current()->Files(level);
for(auto meta:files) {
if(meta->largest_deadtime < nowTime) {
remove = true;
edit.RemoveFile(level,meta->number);
std::cout<<"remove file : "<<meta->number<<" from level : "<<level<<" deadtime : "<<meta->largest_deadtime<<std::endl;
}
}
}
if(remove) {
versions_->LogAndApply(&edit,&mutex_);
// RemoveObsoleteFiles();
}
base->Unref();
return remove;
}
void DBImpl::BackgroundCompaction() {
mutex_.AssertHeld();
@ -713,6 +739,10 @@ void DBImpl::BackgroundCompaction() {
return;
}
if(RemoveExpireTable()) {
return;
}
Compaction* c;
bool is_manual = (manual_compaction_ != nullptr);
InternalKey manual_end;
@ -951,11 +981,20 @@ Status DBImpl::DoCompactionWork(CompactionState* compact) {
// Handle key/value, add to state, etc.
bool drop = false;
time_t nowTime;
time(&nowTime);
if (!ParseInternalKey(key, &ikey)) {
// Do not hide error keys
current_user_key.clear();
has_current_user_key = false;
last_sequence_for_key = kMaxSequenceNumber;
} else if(ikey.deadTime != 0 && ikey.deadTime < nowTime){
static int count = 0;
if(count % 1000 == 0) {
std::cout<<"count "<<count<<" drop dead in Compaction: "<<ikey.user_key.ToString()<<" "<<ikey.deadTime<<std::endl;
count ++;
}
drop = true;
} else {
if (!has_current_user_key ||
user_comparator()->Compare(ikey.user_key, Slice(current_user_key)) !=
@ -981,7 +1020,6 @@ Status DBImpl::DoCompactionWork(CompactionState* compact) {
// Therefore this deletion marker is obsolete and can be dropped.
drop = true;
}
last_sequence_for_key = ikey.sequence;
}
#if 0
@ -993,7 +1031,6 @@ Status DBImpl::DoCompactionWork(CompactionState* compact) {
compact->compaction->IsBaseLevelForKey(ikey.user_key),
(int)last_sequence_for_key, (int)compact->smallest_snapshot);
#endif
if (!drop) {
// Open output file if necessary
if (compact->builder == nullptr) {

+ 1
- 0
db/db_impl.h Vedi File

@ -145,6 +145,7 @@ class DBImpl : public DB {
EXCLUSIVE_LOCKS_REQUIRED(mutex_);
Status DoCompactionWork(CompactionState* compact)
EXCLUSIVE_LOCKS_REQUIRED(mutex_);
bool RemoveExpireTable(); //if remove some table thne return true otherwise return false
Status OpenCompactionOutputFile(CompactionState* compact);
Status FinishCompactionOutputFile(CompactionState* compact, Iterator* input);

+ 3
- 3
db/db_test.cc Vedi File

@ -2117,9 +2117,9 @@ class ModelDB : public DB {
Status Put(const WriteOptions& o, const Slice& k, const Slice& v, uint64_t ttl = 0) override {
return DB::Put(o, k, v, ttl);
}
Status Put(const WriteOptions& o, const Slice& k,const Slice& v,uint64_t ttl) {
return DB::Put(o,k,v);
}
// Status Put(const WriteOptions& o, const Slice& k,const Slice& v,uint64_t ttl) {
// return DB::Put(o,k,v);
// }
Status Delete(const WriteOptions& o, const Slice& key) override {
return DB::Delete(o, key);
}

+ 12
- 11
db/dbformat.cc Vedi File

@ -78,15 +78,15 @@ int InternalKeyComparator::Compare(const Slice& akey, const Slice& bkey) const {
const uint64_t atime = DecodeFixed64(akey.data() + akey.size() - 16);
const uint64_t btime = DecodeFixed64(bkey.data() + bkey.size() - 16);
//原本应该找到了,新加判断
if((btag & 0b100) && (atag & 0b10)){ //一个是查询键,另一个有ttl
const uint64_t atime = DecodeFixed64(akey.data() + akey.size() - 16);
const uint64_t btime = DecodeFixed64(bkey.data() + bkey.size() - 16);
std::cout<<"atime:"<<atime<<" btime:"<<btime<<" "<<aseq<<" "<<bseq<<" "<<btag<<" "<<atag<<std::endl;
if(atime <= btime){//过期了继续找
r = -1;
return r;
}
}
// if((btag & 0b100) && (atag & 0b10)){ //一个是查询键,另一个有ttl
// const uint64_t atime = DecodeFixed64(akey.data() + akey.size() - 16);
// const uint64_t btime = DecodeFixed64(bkey.data() + bkey.size() - 16);
// std::cout<<"atime:"<<atime<<" btime:"<<btime<<" "<<aseq<<" "<<bseq<<" "<<btag<<" "<<atag<<std::endl;
// if(atime <= btime){//过期了继续找
// r = -1;
// return r;
// }
// }
if (aseq < bseq) {
r = +1;
@ -163,10 +163,11 @@ LookupKey::LookupKey(const Slice& user_key, SequenceNumber s, uint64_t nowTime)
dst += usize;
EncodeFixed64(dst, nowTime);
dst += 8;
EncodeFixed64(dst, PackSequenceAndTypeAndTtlAndLookup(s, kValueTypeForSeek, 0, true));
// EncodeFixed64(dst, PackSequenceAndTypeAndTtlAndLookup(s, kValueTypeForSeek, 0, true));
EncodeFixed64(dst, PackSequenceAndTypeAndTtlAndLookup(s, kValueTypeForSeek, 1, false));
dst += 8;
end_ = dst;
printf("lookupkey tag:%lx\n",PackSequenceAndTypeAndTtlAndLookup(s, kValueTypeForSeek, 0, true));
printf("lookupkey tag:%lx\n",PackSequenceAndTypeAndTtlAndLookup(s, kValueTypeForSeek, 1, false));
}
} // namespace leveldb

+ 5
- 1
db/dbformat.h Vedi File

@ -96,6 +96,9 @@ bool ParseInternalKey(const Slice& internal_key, ParsedInternalKey* result);
// Returns the user key portion of an internal key.
inline Slice ExtractUserKey(const Slice& internal_key) {
if(internal_key.size() < 8) {
std::cout<<"wrong key:"<<internal_key.ToString()<<std::endl;
}
assert(internal_key.size() >= 8);
uint64_t num = DecodeFixed64(internal_key.data() + internal_key.size() - 8);
uint8_t havettl = (num & 0b10) >> 1;
@ -195,7 +198,8 @@ inline bool ParseInternalKey(const Slice& internal_key,
result->deadTime = 0;
result->user_key = Slice(internal_key.data(), n - 8);
}
return (c <= static_cast<uint8_t>(kTypeValue));
// return c <= 0b111;
return ((c & 0b1) <= static_cast<uint8_t>(kTypeValue));
}
// A helper class useful for DBImpl::Get()

+ 40
- 2
db/memtable.cc Vedi File

@ -55,7 +55,23 @@ class MemTableIterator : public Iterator {
~MemTableIterator() override = default;
bool Valid() const override { return iter_.Valid(); }
void Seek(const Slice& k) override { iter_.Seek(EncodeKey(&tmp_, k)); }
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(); }
@ -115,13 +131,35 @@ void MemTable::Add(SequenceNumber s, ValueType type, const Slice& key,
std::memcpy(p, value.data(), val_size);
assert(p + val_size == buf + encoded_len);
table_.Insert(buf);
std::cout << "insert:" << key.ToString() <<" deadTime: " << deadTime << std::endl;
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:

+ 2
- 0
db/skiplist.h Vedi File

@ -90,6 +90,8 @@ class SkipList {
// Final state of iterator is Valid() iff list is not empty.
void SeekToLast();
Comparator get_comparator() const {return list_->compare_;}
private:
const SkipList* list_;
Node* node_;

+ 3
- 0
db/version_set.cc Vedi File

@ -263,8 +263,10 @@ static void SaveValue(void* arg, const Slice& ikey, const Slice& v) {
Saver* s = reinterpret_cast<Saver*>(arg);
ParsedInternalKey parsed_key;
if (!ParseInternalKey(ikey, &parsed_key)) {
// std::cout<<"corrupt get"<<std::endl;
s->state = kCorrupt;
} else {
std::cout<<"tar&found"<<parsed_key.user_key.ToString()<<" "<<s->user_key.ToString()<<std::endl;
if (s->ucmp->Compare(parsed_key.user_key, s->user_key) == 0) {
s->state = (parsed_key.type == kTypeValue) ? kFound : kDeleted;
if (s->state == kFound) {
@ -272,6 +274,7 @@ static void SaveValue(void* arg, const Slice& ikey, const Slice& v) {
}
}
}
std::cout<<"state : "<<s->state<<std::endl;
}
static bool NewestFirst(FileMetaData* a, FileMetaData* b) {

+ 2
- 0
db/version_set.h Vedi File

@ -111,6 +111,8 @@ class Version {
int NumFiles(int level) const { return files_[level].size(); }
const std::vector<FileMetaData*>& Files(int level) const {return files_[level]; }
// Return a human readable string that describes this version's contents.
std::string DebugString() const;

+ 11
- 0
table/block.cc Vedi File

@ -14,6 +14,7 @@
#include "table/format.h"
#include "util/coding.h"
#include "util/logging.h"
#include "db/dbformat.h"
namespace leveldb {
@ -216,10 +217,20 @@ class Block::Iter : public Iterator {
SeekToRestartPoint(left);
}
// Linear search (within restart block) for first key >= target
//处理deadtime:从当前位置向后找到最新的未死亡的key
while (true) {
if (!ParseNextKey()) {
return;
}
ParsedInternalKey parsed_target,parsed_key_;
ParseInternalKey(target,&parsed_target);
ParseInternalKey(key_,&parsed_key_);
uint64_t deadtime_tar = parsed_target.deadTime;
uint64_t deadtime_key_ = parsed_key_.deadTime;
if(deadtime_tar == 0) deadtime_tar = UINT64_MAX;
if(deadtime_key_ == 0) deadtime_key_ = UINT64_MAX;
std::cout<<"key :"<<parsed_target.user_key.ToString()<<" tar time: "<<deadtime_tar<<" key time: "<<deadtime_key_<<std::endl;
if(deadtime_tar > deadtime_key_) continue;
if (Compare(key_, target) >= 0) {
return;
}

+ 4
- 4
test/ttl_mmtable_test.cc Vedi File

@ -8,7 +8,7 @@
using namespace leveldb;
constexpr int value_size = 2048;
constexpr int data_size = 2048 << 2;
constexpr int data_size = 2048 << 15;
Status OpenDB(std::string dbName, DB **db) {
Options options;
@ -92,7 +92,7 @@ DB *db;
uint64_t ttl1 = 3;
uint64_t ttl2 = 5;
InsertData(db, ttl2);
// InsertData(db, ttl2);
InsertData(db, ttl1, 2);
//都没过期先找到后插的
@ -101,8 +101,8 @@ DB *db;
//再找到前一次
Env::Default()->SleepForMicroseconds(3 * 1000000);
GetData(db, false);
GetData(db, true);
DestroyDB("testdb",Options());
delete(db);
printf("-----closing-----\n");
printf("success!\n");

+ 32
- 24
test/ttl_test.cc Vedi File

@ -26,7 +26,8 @@ void InsertData(DB *db, uint64_t ttl/* second */) {
int key_ = rand() % key_num+1;
std::string key = std::to_string(key_);
std::string value(value_size, 'a');
db->Put(writeOptions, key, value, ttl);
db->Put(writeOptions, std::to_string(i+1), value, ttl);
// db->Put(writeOptions, key, value, ttl);
}
}
@ -45,13 +46,14 @@ void GetData(DB *db, int size = (1 << 30)) {
}
TEST(TestTTL, ReadTTL) {
DestroyDB("testdb",Options());
DB *db;
if(OpenDB("testdb", &db).ok() == false) {
std::cerr << "open db failed" << std::endl;
abort();
}
uint64_t ttl = 20;
uint64_t ttl = 15;
InsertData(db, ttl);
@ -64,47 +66,53 @@ TEST(TestTTL, ReadTTL) {
std::string key = std::to_string(key_);
std::string value;
status = db->Get(readOptions, key, &value);
std::cout<<key<<" "<<value[0]<<std::endl;
ASSERT_TRUE(status.ok());
}
Env::Default()->SleepForMicroseconds(ttl * 1000000);
Env::Default()->SleepForMicroseconds((ttl+1) * 1000000);
for (int i = 0; i < 100; i++) {
int key_ = rand() % key_num+1;
std::string key = std::to_string(key_);
std::string value;
status = db->Get(readOptions, key, &value);
std::cout<<key<<" "<<value<<std::endl;
ASSERT_FALSE(status.ok());
}
delete db;
}
// TEST(TestTTL, CompactionTTL) {
// DB *db;
TEST(TestTTL, CompactionTTL) {
DestroyDB("testdb",Options());
DB *db;
// if(OpenDB("testdb", &db).ok() == false) {
// std::cerr << "open db failed" << std::endl;
// abort();
// }
if(OpenDB("testdb", &db).ok() == false) {
std::cerr << "open db failed" << std::endl;
abort();
}
// uint64_t ttl = 20;
// InsertData(db, ttl);
uint64_t ttl = 10;
InsertData(db, ttl);
// leveldb::Range ranges[1];
// ranges[0] = leveldb::Range("-", "A");
// uint64_t sizes[1];
// db->GetApproximateSizes(ranges, 1, sizes);
// ASSERT_GT(sizes[0], 0);
leveldb::Range ranges[1];
ranges[0] = leveldb::Range("-", "A");
uint64_t sizes[1];
db->GetApproximateSizes(ranges, 1, sizes);
ASSERT_GT(sizes[0], 0);
// Env::Default()->SleepForMicroseconds(ttl * 1000000);
Env::Default()->SleepForMicroseconds((ttl+1) * 1000000);
// Env::Default()->SleepForMicroseconds(ttl * 1000000);
// db->CompactRange(nullptr, nullptr);
db->CompactRange(nullptr, nullptr);
// leveldb::Range ranges[1];
// ranges[0] = leveldb::Range("-", "A");
// uint64_t sizes[1];
// db->GetApproximateSizes(ranges, 1, sizes);
// ASSERT_EQ(sizes[0], 0);
// }
// leveldb::Range ranges[1];
ranges[0] = leveldb::Range("-", "A");
// uint64_t sizes[1];
db->GetApproximateSizes(ranges, 1, sizes);
ASSERT_EQ(sizes[0], 0);
delete db;
}
int main(int argc, char** argv) {

Caricamento…
Annulla
Salva