ic_memory/runtime/
default.rs1use super::{
2 MemoryRuntime, RuntimeBootstrapError, RuntimeConstructionError, RuntimeDiagnosticError,
3 RuntimeMemory, RuntimeOpenError, RuntimeStateError, policy::NoopPolicy,
4};
5use crate::{
6 CommittedAllocations, DiagnosticExport, MemoryRuntimeDoctorReport, RuntimeBootstrapPolicy,
7 physical::CommitStoreDiagnostic, registry::sealed_declaration_snapshot,
8};
9use ic_stable_structures::DefaultMemoryImpl;
10use std::{cell::RefCell, convert::Infallible, fmt::Display};
11
12thread_local! {
13 static DEFAULT_RUNTIME:
14 RefCell<Option<Result<MemoryRuntime<DefaultMemoryImpl>, RuntimeConstructionError>>> =
15 const { RefCell::new(None) };
16}
17
18fn with_default_runtime<T, E>(
19 operation: impl FnOnce(&MemoryRuntime<DefaultMemoryImpl>) -> Result<T, E>,
20) -> Result<T, E>
21where
22 E: From<RuntimeStateError>,
23{
24 match DEFAULT_RUNTIME.try_with(|runtime| {
25 let mut runtime = runtime
26 .try_borrow_mut()
27 .map_err(|_| E::from(RuntimeStateError::ReentrantAccess))?;
28 let runtime = runtime
29 .get_or_insert_with(|| MemoryRuntime::new(DefaultMemoryImpl::default()))
30 .as_ref()
31 .map_err(|error| E::from(RuntimeStateError::Construction(*error)))?;
32 operation(runtime)
33 }) {
34 Ok(result) => result,
35 Err(_) => Err(E::from(RuntimeStateError::Unavailable)),
36 }
37}
38
39fn with_default_runtime_mut<T, E>(
40 operation: impl FnOnce(&mut MemoryRuntime<DefaultMemoryImpl>) -> Result<T, E>,
41) -> Result<T, E>
42where
43 E: From<RuntimeStateError>,
44{
45 match DEFAULT_RUNTIME.try_with(|runtime| {
46 let mut runtime = runtime
47 .try_borrow_mut()
48 .map_err(|_| E::from(RuntimeStateError::ReentrantAccess))?;
49 let runtime = runtime
50 .get_or_insert_with(|| MemoryRuntime::new(DefaultMemoryImpl::default()))
51 .as_mut()
52 .map_err(|error| E::from(RuntimeStateError::Construction(*error)))?;
53 operation(runtime)
54 }) {
55 Ok(result) => result,
56 Err(_) => Err(E::from(RuntimeStateError::Unavailable)),
57 }
58}
59
60pub fn is_default_memory_manager_bootstrapped() -> Result<bool, RuntimeStateError> {
62 with_default_runtime(|runtime| Ok(runtime.is_bootstrapped()))
63}
64
65pub fn committed_allocations() -> Result<CommittedAllocations, RuntimeOpenError> {
67 with_default_runtime(|runtime| runtime.committed_allocations().cloned())
68}
69
70pub fn bootstrap_default_memory_manager()
72-> Result<CommittedAllocations, RuntimeBootstrapError<Infallible>> {
73 bootstrap_default_memory_manager_with_policy(&NoopPolicy)
74}
75
76pub fn bootstrap_default_memory_manager_with_policy<P: RuntimeBootstrapPolicy>(
83 policy: &P,
84) -> Result<CommittedAllocations, RuntimeBootstrapError<P::Error>> {
85 let declarations = sealed_declaration_snapshot()?;
86 with_default_runtime_mut(|runtime| runtime.bootstrap(&declarations, policy).cloned())
87}
88
89pub fn open_default_memory_manager_memory(
91 stable_key: &str,
92 id: u8,
93) -> Result<RuntimeMemory<DefaultMemoryImpl>, RuntimeOpenError> {
94 with_default_runtime(|runtime| runtime.open_memory(stable_key, id))
95}
96
97pub fn default_memory_manager_diagnostic_export() -> Result<DiagnosticExport, RuntimeDiagnosticError>
99{
100 with_default_runtime(MemoryRuntime::diagnostic_export)
101}
102
103pub fn default_memory_manager_commit_recovery_diagnostic()
105-> Result<CommitStoreDiagnostic, RuntimeDiagnosticError> {
106 with_default_runtime(MemoryRuntime::commit_recovery_diagnostic)
107}
108
109pub fn default_memory_manager_doctor_report()
111-> Result<MemoryRuntimeDoctorReport, RuntimeDiagnosticError> {
112 default_memory_manager_doctor_report_with_policy(&NoopPolicy)
113}
114
115pub fn default_memory_manager_doctor_report_with_policy<P>(
117 policy: &P,
118) -> Result<MemoryRuntimeDoctorReport, RuntimeDiagnosticError>
119where
120 P: RuntimeBootstrapPolicy,
121 P::Error: Display,
122{
123 let declarations = sealed_declaration_snapshot()?;
124 with_default_runtime(|runtime| Ok(runtime.doctor_report(&declarations, policy)))
125}
126
127#[cfg(test)]
128pub(super) fn with_default_runtime_borrowed(
129 operation: impl FnOnce() -> Result<(), RuntimeStateError>,
130) -> Result<(), RuntimeStateError> {
131 DEFAULT_RUNTIME.with(|runtime| {
132 let _borrow = runtime.borrow_mut();
133 operation()
134 })
135}
136
137pub fn default_memory_manager_memory_allocations()
143-> Result<super::MemoryAllocations, RuntimeDiagnosticError> {
144 DEFAULT_RUNTIME
145 .try_with(|runtime| {
146 let runtime = runtime
147 .try_borrow()
148 .map_err(|_| RuntimeStateError::ReentrantAccess)?;
149 let runtime = runtime
150 .as_ref()
151 .ok_or(RuntimeDiagnosticError::NotBootstrapped)?
152 .as_ref()
153 .map_err(|error| RuntimeStateError::Construction(*error))?;
154 runtime.memory_allocations()
155 })
156 .map_err(|_| RuntimeStateError::Unavailable)?
157}
158
159pub fn bootstrap_default_memory_manager_with_config<P: RuntimeBootstrapPolicy>(
166 config: super::MemoryManagerConfig,
167 policy: &P,
168) -> Result<CommittedAllocations, RuntimeBootstrapError<P::Error>> {
169 DEFAULT_RUNTIME
170 .try_with(|runtime| {
171 let mut runtime = runtime
172 .try_borrow_mut()
173 .map_err(|_| RuntimeStateError::ReentrantAccess)?;
174 let runtime = runtime
175 .get_or_insert_with(|| {
176 MemoryRuntime::new_with_config(DefaultMemoryImpl::default(), config)
177 })
178 .as_mut()
179 .map_err(|error| RuntimeStateError::Construction(*error))?;
180 super::check_bucket_size(runtime.bucket_size_pages, config)
181 .map_err(RuntimeStateError::Construction)?;
182 let declarations = sealed_declaration_snapshot()?;
183 runtime.bootstrap(&declarations, policy).cloned()
184 })
185 .map_err(|_| RuntimeStateError::Unavailable)?
186}