in src/device/file_system_disk.h [350:411]
void TruncateSegments(uint64_t new_begin_segment, GcState::truncate_callback_t caller_callback) {
class Context : public IAsyncContext {
public:
Context(bundle_t* files_, uint64_t new_begin_segment_,
GcState::truncate_callback_t caller_callback_)
: files{ files_ }
, new_begin_segment{ new_begin_segment_ }
, caller_callback{ caller_callback_ } {
}
/// The deep-copy constructor.
Context(const Context& other)
: files{ other.files }
, new_begin_segment{ other.new_begin_segment }
, caller_callback{ other.caller_callback } {
}
protected:
Status DeepCopy_Internal(IAsyncContext*& context_copy) final {
return IAsyncContext::DeepCopy_Internal(*this, context_copy);
}
public:
bundle_t* files;
uint64_t new_begin_segment;
GcState::truncate_callback_t caller_callback;
};
auto callback = [](IAsyncContext* ctxt) {
CallbackContext<Context> context{ ctxt };
for(uint64_t idx = context->files->begin_segment; idx < context->new_begin_segment; ++idx) {
file_t& file = context->files->file(idx);
file.Close();
file.Delete();
}
std::free(context->files);
if(context->caller_callback) {
context->caller_callback(context->new_begin_segment * kSegmentSize);
}
};
// Only one thread can modify the list of files at a given time.
std::lock_guard<std::mutex> lock{ mutex_ };
bundle_t* files = files_.load();
assert(files);
if(files->begin_segment >= new_begin_segment) {
// Segments have already been truncated.
if(caller_callback) {
caller_callback(files->begin_segment * kSegmentSize);
}
return;
}
// Make a copy of the list, excluding the files to be truncated.
void* buffer = std::malloc(bundle_t::size(files->end_segment - new_begin_segment));
bundle_t* new_files = new(buffer) bundle_t{ handler_, new_begin_segment, files->end_segment,
*files };
files_.store(new_files);
// Delete the old list only after all threads have finished looking at it.
Context context{ files, new_begin_segment, caller_callback };
IAsyncContext* context_copy;
Status result = context.DeepCopy(context_copy);
assert(result == Status::Ok);
epoch_->BumpCurrentEpoch(callback, context_copy);
}