rust/hg-pyo3/src/store.rs
author Georges Racinet <georges.racinet@cloudcrane.io>
Sun, 22 Dec 2024 17:02:09 +0100
changeset 52792 acae91fad6be
parent 52780 42b219a1404a
permissions -rw-r--r--
rust-pyo3-revlog: standalone NodeTree class This is the actual first usage of `PyShareable`, but perhaps it could be not so much necessary in this case (we could just reference the `InnerRevlog` python object, and we do not need to keep additional state).
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
52776
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
     1
// store.rs
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
     2
//
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
     3
// Copyright 2020-2024 Raphaël Gomès <raphael.gomes@octobus.net>
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
     4
//           2024 Georges Racinet <georges.racinet@cloudcrane.io>
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
     5
//
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
     6
// This software may be used and distributed according to the terms of the
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
     7
// GNU General Public License version 2 or any later version.
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
     8
use pyo3::prelude::*;
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
     9
use pyo3::types::PyBytes;
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
    10
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
    11
use std::sync::atomic::{AtomicBool, Ordering};
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
    12
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
    13
use hg::{fncache::FnCache, utils::files::get_bytes_from_path};
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
    14
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
    15
pub struct PyFnCache {
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
    16
    fncache: PyObject,
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
    17
}
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
    18
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
    19
impl PyFnCache {
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
    20
    pub fn new(fncache: PyObject) -> Self {
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
    21
        Self { fncache }
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
    22
    }
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
    23
}
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
    24
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
    25
impl Clone for PyFnCache {
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
    26
    fn clone(&self) -> Self {
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
    27
        Python::with_gil(|py| Self {
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
    28
            fncache: self.fncache.clone_ref(py),
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
    29
        })
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
    30
    }
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
    31
}
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
    32
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
    33
/// Cache whether the fncache is loaded to avoid Python round-trip every time.
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
    34
/// Once the fncache is loaded, it stays loaded unless we're in a very
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
    35
/// long-running process, none of which we actually support for now.
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
    36
static FN_CACHE_IS_LOADED: AtomicBool = AtomicBool::new(false);
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
    37
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
    38
// TODO perhaps a bit of magic with `Bound<'_, PyFnCache>` would spare us
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
    39
// the GIL reacquisitions
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
    40
impl FnCache for PyFnCache {
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
    41
    fn is_loaded(&self) -> bool {
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
    42
        if FN_CACHE_IS_LOADED.load(Ordering::Relaxed) {
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
    43
            return true;
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
    44
        }
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
    45
        Python::with_gil(|py| {
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
    46
            // TODO raise in case of error?
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
    47
            let is_loaded = self
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
    48
                .fncache
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
    49
                .getattr(py, "is_loaded")
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
    50
                .ok()
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
    51
                .map(|o| {
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
    52
                    o.extract::<bool>(py).expect(
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
    53
                        "is_loaded returned something other than a bool",
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
    54
                    )
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
    55
                })
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
    56
                .unwrap_or(false);
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
    57
            if is_loaded {
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
    58
                FN_CACHE_IS_LOADED.store(true, Ordering::Relaxed);
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
    59
            }
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
    60
            is_loaded
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
    61
        })
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
    62
    }
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
    63
    fn add(&self, path: &std::path::Path) {
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
    64
        Python::with_gil(|py| {
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
    65
            // TODO raise in case of error?
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
    66
            self.fncache
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
    67
                .call_method(
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
    68
                    py,
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
    69
                    "add",
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
    70
                    (PyBytes::new(py, &get_bytes_from_path(path)),),
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
    71
                    None,
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
    72
                )
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
    73
                .ok();
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
    74
        })
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
    75
    }
6fa23eed335b rust-pyo3: PyFnCache
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
    76
}