fn recover_log_file()

in common/rusty_leveldb_sgx/src/db_impl.rs [240:311]


    fn recover_log_file(
        &mut self,
        log_num: FileNum,
        is_last: bool,
        ve: &mut VersionEdit,
    ) -> Result<(bool, SequenceNumber)> {
        let filename = log_file_name(&self.path, log_num);
        let mut compactions = 0;
        let mut max_seq = 0;
        let mut save_manifest = false;
        let cmp: Rc<Box<dyn Cmp>> = self.opt.cmp.clone();
        let mut mem = MemTable::new(cmp.clone());
        {
            let logfile = self.opt.env.open_sequential_file(Path::new(&filename))?;
            // Use the user-supplied comparator; it will be wrapped inside a MemtableKeyCmp.

            let mut logreader = LogReader::new(
                logfile, // checksum=
                true,
            );
            log!(self.opt.log, "Recovering log file {:?}", filename);
            let mut scratch = vec![];
            let mut batch = WriteBatch::new();

            while let Ok(len) = logreader.read(&mut scratch) {
                if len == 0 {
                    break;
                }
                if len < 12 {
                    log!(
                        self.opt.log,
                        "corruption in log file {:06}: record shorter than 12B",
                        log_num
                    );
                    continue;
                }

                batch.set_contents(&scratch);
                batch.insert_into_memtable(batch.sequence(), &mut mem);

                let last_seq = batch.sequence() + batch.count() as u64 - 1;
                if last_seq > max_seq {
                    max_seq = last_seq
                }
                if mem.approx_mem_usage() > self.opt.write_buffer_size {
                    compactions += 1;
                    self.write_l0_table(&mem, ve, None)?;
                    save_manifest = true;
                    mem = MemTable::new(cmp.clone());
                }
                batch.clear();
            }
        }

        // Check if we can reuse the last log file.
        if self.opt.reuse_logs && is_last && compactions == 0 {
            assert!(self.log.is_none());
            log!(self.opt.log, "reusing log file {:?}", filename);
            let oldsize = self.opt.env.size_of(Path::new(&filename))?;
            let oldfile = self.opt.env.open_appendable_file(Path::new(&filename))?;
            let lw = LogWriter::new_with_off(BufWriter::new(oldfile), oldsize);
            self.log = Some(lw);
            self.log_num = Some(log_num);
            self.mem = mem;
        } else if mem.len() > 0 {
            // Log is not reused, so write out the accumulated memtable.
            save_manifest = true;
            self.write_l0_table(&mem, ve, None)?;
        }

        Ok((save_manifest, max_seq))
    }