#[cfg(test)]
mod tests;
use crate::error::InternalError;
use candid::CandidType;
use serde::Deserialize;
#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq)]
pub struct MemoryAllocations {
pub current_generation: Option<u64>,
pub manager_layout_version: u8,
pub bucket_size_pages: u16,
pub bucket_size_bytes: u64,
pub bucket_capacity: u32,
pub allocated_buckets: u16,
pub remaining_buckets: u32,
pub maximum_bucket_bytes: u64,
pub physical_extent: MemoryExtent,
pub virtual_extent: MemoryExtent,
pub manager_metadata_bytes: u64,
pub manager_header_bytes: u64,
pub manager_bucket_table_bytes: u64,
pub manager_padding_bytes: u64,
pub allocated_bucket_bytes: u64,
pub bucket_slack_bytes: u64,
pub known_binding_bytes: u64,
pub unknown_binding_bytes: u64,
pub unmanaged_bytes: u64,
pub metadata_bytes_read: u64,
pub memories: Vec<MemoryAllocation>,
}
impl From<ic_memory::MemoryAllocations> for MemoryAllocations {
fn from(report: ic_memory::MemoryAllocations) -> Self {
Self {
current_generation: report.current_generation,
manager_layout_version: report.manager_layout_version,
bucket_size_pages: report.bucket_size_pages,
bucket_size_bytes: report.bucket_size_bytes,
bucket_capacity: report.bucket_capacity,
allocated_buckets: report.allocated_buckets,
remaining_buckets: report.remaining_buckets,
maximum_bucket_bytes: report.maximum_bucket_bytes,
physical_extent: report.physical_extent.into(),
virtual_extent: report.virtual_extent.into(),
manager_metadata_bytes: report.manager_metadata_bytes,
manager_header_bytes: report.manager_header_bytes,
manager_bucket_table_bytes: report.manager_bucket_table_bytes,
manager_padding_bytes: report.manager_padding_bytes,
allocated_bucket_bytes: report.allocated_bucket_bytes,
bucket_slack_bytes: report.bucket_slack_bytes,
known_binding_bytes: report.known_binding_bytes,
unknown_binding_bytes: report.unknown_binding_bytes,
unmanaged_bytes: report.unmanaged_bytes,
metadata_bytes_read: report.metadata_bytes_read,
memories: report.memories.into_iter().map(Into::into).collect(),
}
}
}
#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq)]
pub struct MemoryExtent {
pub wasm_pages: u64,
pub bytes: u64,
}
impl From<ic_memory::DiagnosticMemorySize> for MemoryExtent {
fn from(extent: ic_memory::DiagnosticMemorySize) -> Self {
Self {
wasm_pages: extent.wasm_pages,
bytes: extent.bytes,
}
}
}
#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq)]
pub enum MemoryAllocationBinding {
Current {
stable_key: String,
owner: String,
},
Ledger {
stable_key: String,
owner: String,
},
Unknown,
}
#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq)]
pub struct MemoryAllocationRangeClaim {
pub authority: String,
pub reserved: bool,
}
#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq)]
pub struct MemoryAllocation {
pub memory_manager_id: u8,
pub binding: MemoryAllocationBinding,
pub range_claim: Option<MemoryAllocationRangeClaim>,
pub virtual_extent: MemoryExtent,
pub allocated_buckets: u16,
pub allocated_bytes: u64,
pub bucket_slack_bytes: u64,
pub payload_bytes: Option<u64>,
}
impl From<ic_memory::MemoryAllocation> for MemoryAllocation {
fn from(memory: ic_memory::MemoryAllocation) -> Self {
Self {
memory_manager_id: memory.memory_manager_id,
binding: match memory.binding {
ic_memory::AllocationBinding::Current { stable_key, owner } => {
MemoryAllocationBinding::Current { stable_key, owner }
}
ic_memory::AllocationBinding::Ledger { stable_key, owner } => {
MemoryAllocationBinding::Ledger { stable_key, owner }
}
ic_memory::AllocationBinding::Unknown => MemoryAllocationBinding::Unknown,
},
range_claim: memory.range_claim.map(|claim| MemoryAllocationRangeClaim {
authority: claim.authority,
reserved: match claim.mode {
ic_memory::MemoryManagerRangeMode::Reserved => true,
ic_memory::MemoryManagerRangeMode::Allowed => false,
},
}),
virtual_extent: memory.virtual_extent.into(),
allocated_buckets: memory.allocated_buckets,
allocated_bytes: memory.allocated_bytes,
bucket_slack_bytes: memory.bucket_slack_bytes,
payload_bytes: memory.payload_bytes,
}
}
}
pub(super) fn collect_memory_allocations() -> Result<Option<MemoryAllocations>, InternalError> {
match ic_memory::default_memory_manager_memory_allocations() {
Ok(report) => Ok(Some(report.into())),
Err(ic_memory::RuntimeDiagnosticError::NotBootstrapped) => Ok(None),
Err(_) => Err(InternalError::store_internal()),
}
}