|
@ -83,6 +83,10 @@ struct DBImpl::CompactionState { |
|
|
WritableFile* outfile; |
|
|
WritableFile* outfile; |
|
|
TableBuilder* builder; |
|
|
TableBuilder* builder; |
|
|
|
|
|
|
|
|
|
|
|
WritableFile* valuelogfile; |
|
|
|
|
|
uint64_t valuelog_offset=0; |
|
|
|
|
|
uint64_t valuelog_file_id=0; |
|
|
|
|
|
|
|
|
uint64_t total_bytes; |
|
|
uint64_t total_bytes; |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
@ -816,6 +820,7 @@ Status DBImpl::OpenCompactionOutputFile(CompactionState* compact) { |
|
|
out.smallest.Clear(); |
|
|
out.smallest.Clear(); |
|
|
out.largest.Clear(); |
|
|
out.largest.Clear(); |
|
|
compact->outputs.push_back(out); |
|
|
compact->outputs.push_back(out); |
|
|
|
|
|
compact->valuelog_file_id=versions_->NewFileNumber(); |
|
|
mutex_.Unlock(); |
|
|
mutex_.Unlock(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@ -825,6 +830,11 @@ Status DBImpl::OpenCompactionOutputFile(CompactionState* compact) { |
|
|
if (s.ok()) { |
|
|
if (s.ok()) { |
|
|
compact->builder = new TableBuilder(options_, compact->outfile); |
|
|
compact->builder = new TableBuilder(options_, compact->outfile); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
compact->valuelog_offset=0; |
|
|
|
|
|
s = env_->NewWritableFile(ValueLogFileName(dbname_,compact->valuelog_file_id), &compact->valuelogfile); |
|
|
|
|
|
|
|
|
return s; |
|
|
return s; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@ -860,6 +870,19 @@ Status DBImpl::FinishCompactionOutputFile(CompactionState* compact, |
|
|
} |
|
|
} |
|
|
delete compact->outfile; |
|
|
delete compact->outfile; |
|
|
compact->outfile = nullptr; |
|
|
compact->outfile = nullptr; |
|
|
|
|
|
if (s.ok()) { |
|
|
|
|
|
s = compact->valuelogfile->Flush(); |
|
|
|
|
|
} |
|
|
|
|
|
if (s.ok()) { |
|
|
|
|
|
s = compact->valuelogfile->Sync(); |
|
|
|
|
|
} |
|
|
|
|
|
if (s.ok()) { |
|
|
|
|
|
s = compact->valuelogfile->Close(); |
|
|
|
|
|
} |
|
|
|
|
|
delete compact->valuelogfile; |
|
|
|
|
|
compact->valuelogfile=nullptr; |
|
|
|
|
|
compact->valuelog_file_id=0; |
|
|
|
|
|
compact->valuelog_offset=0; |
|
|
|
|
|
|
|
|
if (s.ok() && current_entries > 0) { |
|
|
if (s.ok() && current_entries > 0) { |
|
|
// Verify that the table is usable
|
|
|
// Verify that the table is usable
|
|
@ -1004,7 +1027,34 @@ Status DBImpl::DoCompactionWork(CompactionState* compact) { |
|
|
compact->current_output()->smallest.DecodeFrom(key); |
|
|
compact->current_output()->smallest.DecodeFrom(key); |
|
|
} |
|
|
} |
|
|
compact->current_output()->largest.DecodeFrom(key); |
|
|
compact->current_output()->largest.DecodeFrom(key); |
|
|
compact->builder->Add(key, input->value()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Slice old_value=input->value(); |
|
|
|
|
|
Slice new_value; |
|
|
|
|
|
std::string buf=""; |
|
|
|
|
|
if(old_value.data()[0]==(char)(0x00)){ |
|
|
|
|
|
new_value=old_value; |
|
|
|
|
|
} |
|
|
|
|
|
else{ |
|
|
|
|
|
uint64_t file_id,valuelog_offset,valuelog_len; |
|
|
|
|
|
bool res=GetVarint64(&old_value,&file_id); |
|
|
|
|
|
if(!res)assert(0); |
|
|
|
|
|
res=GetVarint64(&old_value,&valuelog_offset); |
|
|
|
|
|
if(!res)assert(0); |
|
|
|
|
|
res=GetVarint64(&old_value,&valuelog_len); |
|
|
|
|
|
if(!res)assert(0); |
|
|
|
|
|
Status s=ReadValueLog(file_id,valuelog_offset,valuelog_len,&new_value); |
|
|
|
|
|
assert(s.ok()); |
|
|
|
|
|
writeValueLogForCompaction(compact->valuelogfile,{new_value}); |
|
|
|
|
|
buf+=(char)(0x01); |
|
|
|
|
|
PutVarint64(&buf,compact->valuelog_file_id); |
|
|
|
|
|
PutVarint64(&buf,compact->valuelog_offset); |
|
|
|
|
|
PutVarint64(&buf,valuelog_len); |
|
|
|
|
|
compact->valuelog_offset+=valuelog_len; |
|
|
|
|
|
delete []new_value.data(); |
|
|
|
|
|
new_value=Slice(buf); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
compact->builder->Add(key, new_value); |
|
|
|
|
|
|
|
|
// Close output file if it is big enough
|
|
|
// Close output file if it is big enough
|
|
|
if (compact->builder->FileSize() >= |
|
|
if (compact->builder->FileSize() >= |
|
@ -1168,6 +1218,7 @@ Status DBImpl::Get(const ReadOptions& options, const Slice& key, |
|
|
return s; |
|
|
return s; |
|
|
} |
|
|
} |
|
|
Slice value_log_slice=Slice(value->c_str()+1,value->length()); |
|
|
Slice value_log_slice=Slice(value->c_str()+1,value->length()); |
|
|
|
|
|
Slice new_value; |
|
|
uint64_t file_id,valuelog_offset,valuelog_len; |
|
|
uint64_t file_id,valuelog_offset,valuelog_len; |
|
|
bool res=GetVarint64(&value_log_slice,&file_id); |
|
|
bool res=GetVarint64(&value_log_slice,&file_id); |
|
|
if(!res)return Status::Corruption("can't decode file id"); |
|
|
if(!res)return Status::Corruption("can't decode file id"); |
|
@ -1175,8 +1226,9 @@ Status DBImpl::Get(const ReadOptions& options, const Slice& key, |
|
|
if(!res)return Status::Corruption("can't decode valuelog offset"); |
|
|
if(!res)return Status::Corruption("can't decode valuelog offset"); |
|
|
res=GetVarint64(&value_log_slice,&valuelog_len); |
|
|
res=GetVarint64(&value_log_slice,&valuelog_len); |
|
|
if(!res)return Status::Corruption("can't decode valuelog len"); |
|
|
if(!res)return Status::Corruption("can't decode valuelog len"); |
|
|
ReadValueLog(file_id,valuelog_offset,valuelog_len,&value_log_slice); |
|
|
|
|
|
*value=std::string(value_log_slice.data(),value_log_slice.size()); |
|
|
|
|
|
|
|
|
ReadValueLog(file_id,valuelog_offset,valuelog_len,&new_value); |
|
|
|
|
|
*value=std::string(new_value.data(),new_value.size()); |
|
|
|
|
|
delete []new_value.data(); |
|
|
return s; |
|
|
return s; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@ -1406,7 +1458,7 @@ Status DBImpl::MakeRoomForWrite(bool force) { |
|
|
RecordBackgroundError(s); |
|
|
RecordBackgroundError(s); |
|
|
} |
|
|
} |
|
|
delete logfile_; |
|
|
delete logfile_; |
|
|
|
|
|
|
|
|
|
|
|
addNewValueLog(); |
|
|
logfile_ = lfile; |
|
|
logfile_ = lfile; |
|
|
logfile_number_ = new_log_number; |
|
|
logfile_number_ = new_log_number; |
|
|
log_ = new log::Writer(lfile); |
|
|
log_ = new log::Writer(lfile); |
|
@ -1502,7 +1554,17 @@ void DBImpl::GetApproximateSizes(const Range* range, int n, uint64_t* sizes) { |
|
|
} |
|
|
} |
|
|
std::vector<std::pair<uint64_t,std::pair<uint64_t,uint64_t>>> DBImpl::WriteValueLog(std::vector<Slice> values){ |
|
|
std::vector<std::pair<uint64_t,std::pair<uint64_t,uint64_t>>> DBImpl::WriteValueLog(std::vector<Slice> values){ |
|
|
//lock
|
|
|
//lock
|
|
|
std::string file_name_=std::to_string(valuelogfile_number_)+".VALUELOG"; |
|
|
|
|
|
|
|
|
// std::vector<std::pair<uint64_t,std::pair<uint64_t,uint64_t>>> res;
|
|
|
|
|
|
// for(int i=0;i<values.size();i++){
|
|
|
|
|
|
// int len=values[i].size();
|
|
|
|
|
|
// valuelogfile_->Append(values[i]);
|
|
|
|
|
|
// res.push_back({valuelogfile_number_,{valuelogfile_offset,len}});
|
|
|
|
|
|
// valuelogfile_offset+=len;
|
|
|
|
|
|
// }
|
|
|
|
|
|
// //unlock
|
|
|
|
|
|
// valuelogfile_->Flush();
|
|
|
|
|
|
// return res;
|
|
|
|
|
|
std::string file_name_=ValueLogFileName(dbname_,valuelogfile_number_); |
|
|
std::ofstream valueFile(file_name_, std::ios::app | std::ios::binary); |
|
|
std::ofstream valueFile(file_name_, std::ios::app | std::ios::binary); |
|
|
if (!valueFile.is_open()) { |
|
|
if (!valueFile.is_open()) { |
|
|
assert(0); |
|
|
assert(0); |
|
@ -1519,16 +1581,30 @@ std::vector>> DBImpl::WriteValue |
|
|
valueFile.close(); |
|
|
valueFile.close(); |
|
|
return res; |
|
|
return res; |
|
|
} |
|
|
} |
|
|
|
|
|
void DBImpl::writeValueLogForCompaction(WritableFile* target_file,std::vector<Slice> values){ |
|
|
|
|
|
for(int i=0;i<values.size();i++){ |
|
|
|
|
|
target_file->Append(values[i]); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
void DBImpl::addNewValueLog(){ |
|
|
void DBImpl::addNewValueLog(){ |
|
|
//lock
|
|
|
//lock
|
|
|
|
|
|
// if(valuelogfile_){
|
|
|
|
|
|
// valuelogfile_->Sync();
|
|
|
|
|
|
// valuelogfile_->Close();
|
|
|
|
|
|
// delete valuelogfile_;
|
|
|
|
|
|
// }
|
|
|
valuelogfile_number_=versions_->NewFileNumber(); |
|
|
valuelogfile_number_=versions_->NewFileNumber(); |
|
|
|
|
|
// valuelogfile_offset=0;
|
|
|
|
|
|
// std::string file_name_=ValueLogFileName(dbname_,valuelogfile_number_);
|
|
|
|
|
|
// env_->NewWritableFile(file_name_,&valuelogfile_);
|
|
|
//unlock
|
|
|
//unlock
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
Status DBImpl::ReadValueLog(uint64_t file_id, uint64_t offset,uint64_t len,Slice* value){ |
|
|
Status DBImpl::ReadValueLog(uint64_t file_id, uint64_t offset,uint64_t len,Slice* value){ |
|
|
//lock_shared
|
|
|
//lock_shared
|
|
|
std::string file_name_=std::to_string(valuelogfile_number_)+".VALUELOG"; |
|
|
|
|
|
|
|
|
std::string file_name_=ValueLogFileName(dbname_,file_id); |
|
|
|
|
|
//std::cout<<file_name_<<" "<<offset<<" "<<len<<std::endl;
|
|
|
std::ifstream inFile(file_name_, std::ios::in | std::ios::binary); |
|
|
std::ifstream inFile(file_name_, std::ios::in | std::ios::binary); |
|
|
if (!inFile.is_open()) { |
|
|
if (!inFile.is_open()) { |
|
|
std::cerr << "Failed to open file for writing!" << std::endl; |
|
|
std::cerr << "Failed to open file for writing!" << std::endl; |
|
@ -1538,9 +1614,8 @@ Status DBImpl::ReadValueLog(uint64_t file_id, uint64_t offset,uint64_t len,Slice |
|
|
char *value_buf=new char[len]; |
|
|
char *value_buf=new char[len]; |
|
|
inFile.read(value_buf,len); |
|
|
inFile.read(value_buf,len); |
|
|
inFile.close(); |
|
|
inFile.close(); |
|
|
value=new Slice(value_buf,len); |
|
|
|
|
|
|
|
|
*value=Slice(value_buf,len); |
|
|
return Status::OK(); |
|
|
return Status::OK(); |
|
|
//unlock_shared
|
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// Default implementations of convenience methods that subclasses of DB
|
|
|
// Default implementations of convenience methods that subclasses of DB
|
|
@ -1581,6 +1656,7 @@ Status DB::Open(const Options& options, const std::string& dbname, DB** dbptr) { |
|
|
impl->log_ = new log::Writer(lfile); |
|
|
impl->log_ = new log::Writer(lfile); |
|
|
impl->mem_ = new MemTable(impl->internal_comparator_); |
|
|
impl->mem_ = new MemTable(impl->internal_comparator_); |
|
|
impl->mem_->Ref(); |
|
|
impl->mem_->Ref(); |
|
|
|
|
|
impl->addNewValueLog(); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
if (s.ok() && save_manifest) { |
|
|
if (s.ok() && save_manifest) { |
|
|