sled 0.34.7

Lightweight high-performance pure-rust transactional embedded database.
Documentation
use std::fs::File;
use std::io::{self, Read, Seek, Write};

use parking_lot::Mutex;

use super::LogOffset;

fn init_mu() -> Mutex<()> {
    Mutex::new(())
}

type MutexInit = fn() -> Mutex<()>;

static GLOBAL_FILE_LOCK: crate::Lazy<Mutex<()>, MutexInit> =
    crate::Lazy::new(init_mu);

pub(crate) fn pread_exact_or_eof(
    file: &File,
    mut buf: &mut [u8],
    offset: LogOffset,
) -> io::Result<usize> {
    let _lock = GLOBAL_FILE_LOCK.lock();

    let mut f = file.try_clone()?;

    let _ = f.seek(io::SeekFrom::Start(offset))?;

    let mut total = 0;
    while !buf.is_empty() {
        match f.read(buf) {
            Ok(0) => break,
            Ok(n) => {
                total += n;
                let tmp = buf;
                buf = &mut tmp[n..];
            }
            Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
            Err(e) => return Err(e),
        }
    }
    Ok(total)
}

pub(crate) fn pread_exact(
    file: &File,
    mut buf: &mut [u8],
    offset: LogOffset,
) -> io::Result<()> {
    let _lock = GLOBAL_FILE_LOCK.lock();

    let mut f = file.try_clone()?;

    let _ = f.seek(io::SeekFrom::Start(offset))?;

    while !buf.is_empty() {
        match f.read(buf) {
            Ok(0) => break,
            Ok(n) => {
                let tmp = buf;
                buf = &mut tmp[n..];
            }
            Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
            Err(e) => return Err(e),
        }
    }
    if !buf.is_empty() {
        Err(io::Error::new(
            io::ErrorKind::UnexpectedEof,
            "failed to fill whole buffer",
        ))
    } else {
        Ok(())
    }
}

pub(crate) fn pwrite_all(
    file: &File,
    mut buf: &[u8],
    offset: LogOffset,
) -> io::Result<()> {
    let _lock = GLOBAL_FILE_LOCK.lock();

    let mut f = file.try_clone()?;

    let _ = f.seek(io::SeekFrom::Start(offset))?;

    while !buf.is_empty() {
        match f.write(buf) {
            Ok(0) => {
                return Err(io::Error::new(
                    io::ErrorKind::WriteZero,
                    "failed to write whole buffer",
                ));
            }
            Ok(n) => buf = &buf[n..],
            Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
            Err(e) => return Err(e),
        }
    }
    Ok(())
}