in common/rusty_leveldb_sgx/src/db_impl.rs [161:235]
fn recover(&mut self, ve: &mut VersionEdit) -> Result<bool> {
if self.opt.error_if_exists && self.opt.env.exists(&self.path.as_ref()).unwrap_or(false) {
return err(StatusCode::AlreadyExists, "database already exists");
}
let _ = self.opt.env.mkdir(Path::new(&self.path));
self.acquire_lock()?;
if let Err(e) = read_current_file(&self.opt.env, &self.path) {
if e.code == StatusCode::NotFound && self.opt.create_if_missing {
self.initialize_db()?;
} else {
return err(
StatusCode::InvalidArgument,
"database does not exist and create_if_missing is false",
);
}
}
// If save_manifest is true, we should log_and_apply() later in order to write the new
// manifest.
let mut save_manifest = self.vset.borrow_mut().recover()?;
// Recover from all log files not in the descriptor.
let mut max_seq = 0;
let filenames = self.opt.env.children(&self.path)?;
let mut expected = self.vset.borrow().live_files();
let mut log_files = vec![];
for file in &filenames {
if file
.to_str()
.ok_or_else(|| Status::new(StatusCode::InvalidArgument, "not valid UTF-8"))?
.ends_with(SGX_RECOVERY_FILE_SUFFIX)
{
continue;
}
match parse_file_name(&file) {
Ok((num, typ)) => {
expected.remove(&num);
if typ == FileType::Log
&& (num >= self.vset.borrow().log_num
|| num == self.vset.borrow().prev_log_num)
{
log_files.push(num);
}
}
Err(e) => return Err(e.annotate(format!("While parsing {:?}", file))),
}
}
if !expected.is_empty() {
log!(self.opt.log, "Missing at least these files: {:?}", expected);
return err(StatusCode::Corruption, "missing live files (see log)");
}
log_files.sort();
for i in 0..log_files.len() {
let (save_manifest_, max_seq_) =
self.recover_log_file(log_files[i], i == log_files.len() - 1, ve)?;
if save_manifest_ {
save_manifest = true;
}
if max_seq_ > max_seq {
max_seq = max_seq_;
}
self.vset.borrow_mut().mark_file_number_used(log_files[i]);
}
if self.vset.borrow().last_seq < max_seq {
self.vset.borrow_mut().last_seq = max_seq;
}
Ok(save_manifest)
}