use crate::ffi;
use libc::c_uchar;
use std::borrow::Cow;
use std::ffi::CStr;
use std::fmt;
use std::iter::FusedIterator;
use std::marker::PhantomData;
use std::ops::Range;
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum WalFileType {
ArchivedLogFile,
AliveLogFile,
Unknown,
}
impl From<i32> for WalFileType {
fn from(value: i32) -> Self {
const ARCHIVED: i32 = ffi::rocksdb_wal_file_type_archived_log as i32;
const ALIVE: i32 = ffi::rocksdb_wal_file_type_alive_log as i32;
match value {
ARCHIVED => WalFileType::ArchivedLogFile,
ALIVE => WalFileType::AliveLogFile,
_ => WalFileType::Unknown,
}
}
}
impl WalFileType {
pub fn as_str(self) -> &'static str {
match self {
WalFileType::ArchivedLogFile => "ArchivedLogFile",
WalFileType::AliveLogFile => "AliveLogFile",
WalFileType::Unknown => "Unknown",
}
}
}
pub struct WalReadOptions {
pub(crate) inner: *mut ffi::rocksdb_wal_readoptions_t,
}
impl Default for WalReadOptions {
fn default() -> Self {
let opts = unsafe { ffi::rocksdb_wal_readoptions_create() };
assert!(!opts.is_null(), "Could not create RocksDB WAL Read Options");
Self { inner: opts }
}
}
impl Drop for WalReadOptions {
fn drop(&mut self) {
unsafe {
ffi::rocksdb_wal_readoptions_destroy(self.inner);
}
}
}
unsafe impl Send for WalReadOptions {}
unsafe impl Sync for WalReadOptions {}
impl WalReadOptions {
pub fn set_verify_checksums(&mut self, verify_checksums: bool) {
unsafe {
ffi::rocksdb_wal_readoptions_set_verify_checksums(
self.inner,
c_uchar::from(verify_checksums),
);
}
}
pub fn get_verify_checksums(&self) -> bool {
unsafe { ffi::rocksdb_wal_readoptions_get_verify_checksums(self.inner) != 0 }
}
}
pub struct WalFiles {
inner: *mut ffi::rocksdb_wal_files_t,
len: usize,
}
impl WalFiles {
pub(crate) unsafe fn from_ptr(ptr: *mut ffi::rocksdb_wal_files_t) -> Self {
let len = unsafe { ffi::rocksdb_wal_files_count(ptr.cast_const()) };
Self { inner: ptr, len }
}
pub fn len(&self) -> usize {
self.len
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn get(&self, index: usize) -> Option<WalFile<'_>> {
let inner = unsafe { ffi::rocksdb_wal_files_get_wal_file(self.inner.cast_const(), index) };
if inner.is_null() {
return None;
}
Some(WalFile {
inner,
_files: PhantomData,
})
}
pub fn iter(&self) -> WalFilesIter<'_> {
WalFilesIter {
files: self,
range: 0..self.len,
}
}
}
impl Drop for WalFiles {
fn drop(&mut self) {
unsafe { ffi::rocksdb_wal_files_destroy(self.inner) }
}
}
impl fmt::Debug for WalFiles {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_list().entries(self.iter()).finish()
}
}
impl<'a> IntoIterator for &'a WalFiles {
type Item = WalFile<'a>;
type IntoIter = WalFilesIter<'a>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
unsafe impl Send for WalFiles {}
unsafe impl Sync for WalFiles {}
pub struct WalFilesIter<'a> {
files: &'a WalFiles,
range: Range<usize>,
}
impl<'a> Iterator for WalFilesIter<'a> {
type Item = WalFile<'a>;
fn next(&mut self) -> Option<Self::Item> {
self.files.get(self.range.next()?)
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.range.size_hint()
}
}
impl DoubleEndedIterator for WalFilesIter<'_> {
fn next_back(&mut self) -> Option<Self::Item> {
self.files.get(self.range.next_back()?)
}
}
impl ExactSizeIterator for WalFilesIter<'_> {}
impl FusedIterator for WalFilesIter<'_> {}
#[derive(Copy, Clone)]
pub struct WalFile<'a> {
inner: *const ffi::rocksdb_wal_file_t,
_files: PhantomData<&'a WalFiles>,
}
unsafe impl Send for WalFile<'_> {}
unsafe impl Sync for WalFile<'_> {}
impl<'a> WalFile<'a> {
pub fn path_name(self) -> &'a [u8] {
unsafe { CStr::from_ptr(ffi::rocksdb_wal_file_path_name(self.inner).cast()) }.to_bytes()
}
pub fn path_name_lossy(self) -> Cow<'a, str> {
String::from_utf8_lossy(self.path_name())
}
pub fn log_number(self) -> u64 {
unsafe { ffi::rocksdb_wal_file_log_number(self.inner) }
}
pub fn size_file_bytes(self) -> u64 {
unsafe { ffi::rocksdb_wal_file_size_file_bytes(self.inner) }
}
pub fn start_sequence(self) -> u64 {
unsafe { ffi::rocksdb_wal_file_start_sequence(self.inner) }
}
pub fn file_type(self) -> WalFileType {
WalFileType::from(unsafe { ffi::rocksdb_wal_file_type(self.inner) })
}
}
impl fmt::Debug for WalFile<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("WalFile")
.field("path_name", &self.path_name_lossy())
.field("log_number", &self.log_number())
.field("size_file_bytes", &self.size_file_bytes())
.field("start_sequence", &self.start_sequence())
.field("file_type", &self.file_type())
.finish_non_exhaustive()
}
}
pub struct OwnedWalFile {
inner: *mut ffi::rocksdb_wal_file_t,
}
unsafe impl Send for OwnedWalFile {}
unsafe impl Sync for OwnedWalFile {}
impl OwnedWalFile {
pub(crate) unsafe fn from_ptr(ptr: *mut ffi::rocksdb_wal_file_t) -> Self {
Self { inner: ptr }
}
pub fn as_wal_file(&self) -> WalFile<'_> {
WalFile {
inner: self.inner.cast_const(),
_files: PhantomData,
}
}
pub fn path_name(&self) -> &[u8] {
self.as_wal_file().path_name()
}
pub fn path_name_lossy(&self) -> Cow<'_, str> {
self.as_wal_file().path_name_lossy()
}
pub fn log_number(&self) -> u64 {
self.as_wal_file().log_number()
}
pub fn size_file_bytes(&self) -> u64 {
self.as_wal_file().size_file_bytes()
}
pub fn start_sequence(&self) -> u64 {
self.as_wal_file().start_sequence()
}
pub fn file_type(&self) -> WalFileType {
self.as_wal_file().file_type()
}
}
impl Drop for OwnedWalFile {
fn drop(&mut self) {
unsafe { ffi::rocksdb_wal_file_destroy(self.inner) }
}
}
impl fmt::Debug for OwnedWalFile {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("OwnedWalFile")
.field("path_name", &self.path_name_lossy())
.field("log_number", &self.log_number())
.field("size_file_bytes", &self.size_file_bytes())
.field("start_sequence", &self.start_sequence())
.field("file_type", &self.file_type())
.finish_non_exhaustive()
}
}