|
@ -4,14 +4,6 @@ |
|
|
|
|
|
|
|
|
#include "db/db_impl.h"
|
|
|
#include "db/db_impl.h"
|
|
|
|
|
|
|
|
|
#include <algorithm>
|
|
|
|
|
|
#include <atomic>
|
|
|
|
|
|
#include <cstdint>
|
|
|
|
|
|
#include <cstdio>
|
|
|
|
|
|
#include <set>
|
|
|
|
|
|
#include <string>
|
|
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
|
|
|
|
#include "db/builder.h"
|
|
|
#include "db/builder.h"
|
|
|
#include "db/db_iter.h"
|
|
|
#include "db/db_iter.h"
|
|
|
#include "db/dbformat.h"
|
|
|
#include "db/dbformat.h"
|
|
@ -22,11 +14,22 @@ |
|
|
#include "db/table_cache.h"
|
|
|
#include "db/table_cache.h"
|
|
|
#include "db/version_set.h"
|
|
|
#include "db/version_set.h"
|
|
|
#include "db/write_batch_internal.h"
|
|
|
#include "db/write_batch_internal.h"
|
|
|
|
|
|
#include <algorithm>
|
|
|
|
|
|
#include <atomic>
|
|
|
|
|
|
#include <cstdint>
|
|
|
|
|
|
#include <cstdio>
|
|
|
|
|
|
#include <iostream>
|
|
|
|
|
|
#include <ostream>
|
|
|
|
|
|
#include <set>
|
|
|
|
|
|
#include <string>
|
|
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
|
#include "leveldb/db.h"
|
|
|
#include "leveldb/db.h"
|
|
|
#include "leveldb/env.h"
|
|
|
#include "leveldb/env.h"
|
|
|
#include "leveldb/status.h"
|
|
|
#include "leveldb/status.h"
|
|
|
#include "leveldb/table.h"
|
|
|
#include "leveldb/table.h"
|
|
|
#include "leveldb/table_builder.h"
|
|
|
#include "leveldb/table_builder.h"
|
|
|
|
|
|
|
|
|
#include "port/port.h"
|
|
|
#include "port/port.h"
|
|
|
#include "table/block.h"
|
|
|
#include "table/block.h"
|
|
|
#include "table/merger.h"
|
|
|
#include "table/merger.h"
|
|
@ -591,7 +594,7 @@ void DBImpl::CompactRange(const Slice* begin, const Slice* end) { |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
TEST_CompactMemTable(); // TODO(sanjay): Skip if memtable does not overlap
|
|
|
TEST_CompactMemTable(); // TODO(sanjay): Skip if memtable does not overlap
|
|
|
for (int level = 0; level < max_level_with_files; level++) { |
|
|
|
|
|
|
|
|
for (int level = 0; level < max_level_with_files + 1; level++) { |
|
|
TEST_CompactRange(level, begin, end); |
|
|
TEST_CompactRange(level, begin, end); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
@ -599,10 +602,14 @@ void DBImpl::CompactRange(const Slice* begin, const Slice* end) { |
|
|
void DBImpl::TEST_CompactRange(int level, const Slice* begin, |
|
|
void DBImpl::TEST_CompactRange(int level, const Slice* begin, |
|
|
const Slice* end) { |
|
|
const Slice* end) { |
|
|
assert(level >= 0); |
|
|
assert(level >= 0); |
|
|
assert(level + 1 < config::kNumLevels); |
|
|
|
|
|
|
|
|
assert(level < config::kNumLevels); |
|
|
|
|
|
|
|
|
InternalKey begin_storage, end_storage; |
|
|
InternalKey begin_storage, end_storage; |
|
|
|
|
|
|
|
|
|
|
|
if (level == config::kNumLevels - 1) { |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
ManualCompaction manual; |
|
|
ManualCompaction manual; |
|
|
manual.level = level; |
|
|
manual.level = level; |
|
|
manual.done = false; |
|
|
manual.done = false; |
|
@ -888,8 +895,14 @@ Status DBImpl::InstallCompactionResults(CompactionState* compact) { |
|
|
const int level = compact->compaction->level(); |
|
|
const int level = compact->compaction->level(); |
|
|
for (size_t i = 0; i < compact->outputs.size(); i++) { |
|
|
for (size_t i = 0; i < compact->outputs.size(); i++) { |
|
|
const CompactionState::Output& out = compact->outputs[i]; |
|
|
const CompactionState::Output& out = compact->outputs[i]; |
|
|
compact->compaction->edit()->AddFile(level + 1, out.number, out.file_size, |
|
|
|
|
|
out.smallest, out.largest); |
|
|
|
|
|
|
|
|
if (level < config::kNumLevels - 1) { |
|
|
|
|
|
compact->compaction->edit()->AddFile(level + 1, out.number, out.file_size, |
|
|
|
|
|
out.smallest, out.largest); |
|
|
|
|
|
} else { |
|
|
|
|
|
// TTL: outputs of last level compaction should be writen to last level itself
|
|
|
|
|
|
compact->compaction->edit()->AddFile(level, out.number, out.file_size, |
|
|
|
|
|
out.smallest, out.largest); |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
return versions_->LogAndApply(compact->compaction->edit(), &mutex_); |
|
|
return versions_->LogAndApply(compact->compaction->edit(), &mutex_); |
|
|
} |
|
|
} |
|
@ -963,6 +976,11 @@ Status DBImpl::DoCompactionWork(CompactionState* compact) { |
|
|
last_sequence_for_key = kMaxSequenceNumber; |
|
|
last_sequence_for_key = kMaxSequenceNumber; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
std::string value = input->value().ToString(); |
|
|
|
|
|
uint64_t ddl; |
|
|
|
|
|
DecodeDeadLineValue(&value, ddl); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (last_sequence_for_key <= compact->smallest_snapshot) { |
|
|
if (last_sequence_for_key <= compact->smallest_snapshot) { |
|
|
// Hidden by an newer entry for same user key
|
|
|
// Hidden by an newer entry for same user key
|
|
|
drop = true; // (A)
|
|
|
drop = true; // (A)
|
|
@ -977,6 +995,9 @@ Status DBImpl::DoCompactionWork(CompactionState* compact) { |
|
|
// few iterations of this loop (by rule (A) above).
|
|
|
// few iterations of this loop (by rule (A) above).
|
|
|
// Therefore this deletion marker is obsolete and can be dropped.
|
|
|
// Therefore this deletion marker is obsolete and can be dropped.
|
|
|
drop = true; |
|
|
drop = true; |
|
|
|
|
|
} else if (ddl <= std::time(nullptr)) { |
|
|
|
|
|
// TTL: data expired
|
|
|
|
|
|
drop = true; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
last_sequence_for_key = ikey.sequence; |
|
|
last_sequence_for_key = ikey.sequence; |
|
@ -1042,7 +1063,12 @@ Status DBImpl::DoCompactionWork(CompactionState* compact) { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
mutex_.Lock(); |
|
|
mutex_.Lock(); |
|
|
stats_[compact->compaction->level() + 1].Add(stats); |
|
|
|
|
|
|
|
|
if (compact->compaction->level() + 1 < config::kNumLevels) { |
|
|
|
|
|
stats_[compact->compaction->level() + 1].Add(stats); |
|
|
|
|
|
} else { |
|
|
|
|
|
// TTL: compaction for last level
|
|
|
|
|
|
stats_[compact->compaction->level()].Add(stats); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
if (status.ok()) { |
|
|
if (status.ok()) { |
|
|
status = InstallCompactionResults(compact); |
|
|
status = InstallCompactionResults(compact); |
|
@ -1152,6 +1178,21 @@ Status DBImpl::Get(const ReadOptions& options, const Slice& key, |
|
|
s = current->Get(options, lkey, value, &stats); |
|
|
s = current->Get(options, lkey, value, &stats); |
|
|
have_stat_update = true; |
|
|
have_stat_update = true; |
|
|
} |
|
|
} |
|
|
|
|
|
// TTL: Get the true value and make sure the data is still living
|
|
|
|
|
|
if(!value->empty()) { |
|
|
|
|
|
uint64_t dead_line; |
|
|
|
|
|
DecodeDeadLineValue(value, dead_line); |
|
|
|
|
|
if (dead_line != 0) { |
|
|
|
|
|
// use TTL
|
|
|
|
|
|
if (std::time(nullptr) >= dead_line) { |
|
|
|
|
|
// data expired
|
|
|
|
|
|
*value = ""; |
|
|
|
|
|
s = Status::NotFound("Data expired"); |
|
|
|
|
|
} |
|
|
|
|
|
} else { |
|
|
|
|
|
// TTL not set
|
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
mutex_.Lock(); |
|
|
mutex_.Lock(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@ -1198,6 +1239,11 @@ Status DBImpl::Put(const WriteOptions& o, const Slice& key, const Slice& val) { |
|
|
return DB::Put(o, key, val); |
|
|
return DB::Put(o, key, val); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Status DBImpl::Put(const WriteOptions& options, const Slice& key, |
|
|
|
|
|
const Slice& value, uint64_t ttl) { |
|
|
|
|
|
return DB::Put(options, key, value, ttl); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
Status DBImpl::Delete(const WriteOptions& options, const Slice& key) { |
|
|
Status DBImpl::Delete(const WriteOptions& options, const Slice& key) { |
|
|
return DB::Delete(options, key); |
|
|
return DB::Delete(options, key); |
|
|
} |
|
|
} |
|
@ -1485,12 +1531,22 @@ void DBImpl::GetApproximateSizes(const Range* range, int n, uint64_t* sizes) { |
|
|
|
|
|
|
|
|
// Default implementations of convenience methods that subclasses of DB
|
|
|
// Default implementations of convenience methods that subclasses of DB
|
|
|
// can call if they wish
|
|
|
// can call if they wish
|
|
|
|
|
|
// TTL: Update TTL Encode
|
|
|
Status DB::Put(const WriteOptions& opt, const Slice& key, const Slice& value) { |
|
|
Status DB::Put(const WriteOptions& opt, const Slice& key, const Slice& value) { |
|
|
WriteBatch batch; |
|
|
WriteBatch batch; |
|
|
batch.Put(key, value); |
|
|
|
|
|
|
|
|
batch.Put(key, EncodeDeadLine(0, value)); |
|
|
return Write(opt, &batch); |
|
|
return Write(opt, &batch); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// TTL: Put methods for ttl
|
|
|
|
|
|
Status DB::Put(const WriteOptions& options, const Slice& key, |
|
|
|
|
|
const Slice& value, uint64_t ttl) { |
|
|
|
|
|
WriteBatch batch; |
|
|
|
|
|
auto dead_line = std::time(nullptr) + ttl; |
|
|
|
|
|
batch.Put(key, EncodeDeadLine(dead_line, value)); |
|
|
|
|
|
return Write(options, &batch); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
Status DB::Delete(const WriteOptions& opt, const Slice& key) { |
|
|
Status DB::Delete(const WriteOptions& opt, const Slice& key) { |
|
|
WriteBatch batch; |
|
|
WriteBatch batch; |
|
|
batch.Delete(key); |
|
|
batch.Delete(key); |
|
|