harmos-storage 0.1.5

Harmos storage: durable journals, snapshots and Arrow-backed stream storage.
Documentation
/* ***
 *
 * Harmos
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * ***
 */

/* === Modules === */

/* === Re-Exports === */

/* === Imports === */

// Standard Library Imports

// Third Party Imports

// Local Imports
use super::*;

/* === Constants === */

/* === Macros === */

/* === Type Aliases === */

/* === Structs === */

/* === Enums === */

/* === Traits === */

/* === Implementations === */

impl<C> StorageManager<C> {
    pub async fn close(&self) -> Result<()> {
        {
            let mut state = self.inner.state.lock().unwrap();
            state.status.closing = true;
            state.close_followers();
        }
        self.inner.notify();

        let mut lifecycle = self.inner.lifecycle.write().await;
        let ready = {
            let state = self.inner.state.lock().unwrap();
            state.ready && !state.status.closed
        };
        if ready {
            self.settle_transition().await;
            self.settle_files().await?;
            self.settle_deletions().await?;
            let files = self.capture_files(None)?;
            self.flush_domain(Domain::Data, None).await?;
            self.persist_files(&files).await?;
            self.retire_files();
            self.flush_recovery().await?;
        }
        if ready {
            self.release_snapshots().await?;
        }
        // Closing prevents new maintenance; let an in-flight backend call settle
        // before releasing its physical owner, including uncertain failed calls.
        let mut changed = self.inner.changed.subscribe();
        loop {
            {
                let state = self.inner.state.lock().unwrap();
                if !state.pruning_objects {
                    break;
                }
                if !state.status.running {
                    return Err(Error::NotReady { domain: "storage worker" });
                }
            }
            changed.changed().await.map_err(|_| Error::NotReady { domain: "storage" })?;
        }
        if lifecycle.primary_touched && !lifecycle.primary_closed {
            self.inner.primary.close().await?;
            lifecycle.primary_closed = true;
        }
        if lifecycle.recovery_touched && !lifecycle.recovery_closed {
            self.inner.recovery.close().await?;
            lifecycle.recovery_closed = true;
        }
        // Release Recovered Files Even When Startup Failed Before Readiness.
        self.retire_files();
        {
            let mut state = self.inner.state.lock().unwrap();
            state.receipts.clear();
            state.status.closed = true;
            state.collect();
        }
        self.inner.notify();
        if let Some(owner) = &lifecycle.owner {
            owner.stop().await?;
        }
        lifecycle.owner = None;
        // A supervisor stopped before its first poll never enters the worker's
        // running guard. The completed join is authoritative in either case.
        self.inner.state.lock().unwrap().status.running = false;
        self.inner.notify();
        Ok(())
    }

    pub(super) fn check_raw_recovery(&self) -> Result<()> {
        if self.inner.state.lock().unwrap().journal_saved.is_some() {
            return Err(Error::InvalidInput { field: "recovery ownership", reason: "managed journal owns recovery writes" });
        }
        Ok(())
    }
}

/* === Public Functions === */

/* === Private Functions === */

/* === Tests === */