use std::sync::{Arc, Weak};
use crate::ManagerId;
use crate::blocks::pin::{LifecyclePin, LifecyclePinRef};
use crate::blocks::{BlockId, BlockMetadata, BlockRegistrationHandle, SequenceHash};
use crate::pools::{BlockStore, store::upgrade_or_resurrect};
pub(crate) struct ImmutableBlockInner<T: BlockMetadata> {
store: Arc<BlockStore<T>>,
block_id: BlockId,
seq_hash: SequenceHash,
handle: BlockRegistrationHandle,
is_primary: bool,
_primary_keepalive: Option<Arc<ImmutableBlockInner<T>>>,
}
impl<T: BlockMetadata + Sync> ImmutableBlockInner<T> {
pub(crate) fn new_primary(
store: Arc<BlockStore<T>>,
block_id: BlockId,
seq_hash: SequenceHash,
handle: BlockRegistrationHandle,
) -> Arc<Self> {
Arc::new(Self {
store,
block_id,
seq_hash,
handle,
is_primary: true,
_primary_keepalive: None,
})
}
pub(crate) fn new_duplicate(
store: Arc<BlockStore<T>>,
block_id: BlockId,
seq_hash: SequenceHash,
handle: BlockRegistrationHandle,
primary: Arc<ImmutableBlockInner<T>>,
) -> Arc<Self> {
Arc::new(Self {
store,
block_id,
seq_hash,
handle,
is_primary: false,
_primary_keepalive: Some(primary),
})
}
pub(crate) fn block_id(&self) -> BlockId {
self.block_id
}
pub(crate) fn sequence_hash(&self) -> SequenceHash {
self.seq_hash
}
}
impl<T: BlockMetadata + Sync> LifecyclePin for ImmutableBlockInner<T> {
fn block_id(&self) -> BlockId {
self.block_id
}
fn sequence_hash(&self) -> SequenceHash {
self.seq_hash
}
fn manager_id(&self) -> ManagerId {
self.store.id()
}
fn registration_handle(&self) -> BlockRegistrationHandle {
self.handle.clone()
}
}
impl<T: BlockMetadata> Drop for ImmutableBlockInner<T> {
fn drop(&mut self) {
let self_ptr = self as *const ImmutableBlockInner<T> as *const ();
if self.is_primary {
self.store.release_primary(self.block_id, self_ptr);
} else {
self.store.release_duplicate(self.block_id, self_ptr);
}
}
}
pub struct ImmutableBlock<T: BlockMetadata> {
inner: Arc<ImmutableBlockInner<T>>,
}
impl<T: BlockMetadata + Sync> ImmutableBlock<T> {
pub(crate) fn from_inner(inner: Arc<ImmutableBlockInner<T>>) -> Self {
inner.store.metrics().inc_inflight_immutable();
Self { inner }
}
pub fn downgrade(&self) -> WeakBlock<T> {
WeakBlock {
sequence_hash: self.inner.seq_hash,
inner: Arc::downgrade(&self.inner),
handle: self.inner.handle.clone(),
store: self.inner.store.clone(),
}
}
pub fn block_id(&self) -> BlockId {
self.inner.block_id
}
pub fn sequence_hash(&self) -> SequenceHash {
self.inner.seq_hash
}
pub fn registration_handle(&self) -> BlockRegistrationHandle {
self.inner.handle.clone()
}
pub fn use_count(&self) -> usize {
Arc::strong_count(&self.inner)
}
pub fn set_evict_on_reset(&self, value: bool) {
self.inner
.store
.store_reset_on_release(self.inner.block_id, value);
}
pub fn pin(&self) -> LifecyclePinRef {
LifecyclePinRef::new(self.inner.clone() as Arc<dyn LifecyclePin>)
}
}
impl<T: BlockMetadata + Sync> Clone for ImmutableBlock<T> {
fn clone(&self) -> Self {
self.inner.store.metrics().inc_inflight_immutable();
Self {
inner: self.inner.clone(),
}
}
}
impl<T: BlockMetadata> Drop for ImmutableBlock<T> {
#[inline]
fn drop(&mut self) {
self.inner.store.metrics().dec_inflight_immutable();
}
}
impl<T: BlockMetadata> std::fmt::Debug for ImmutableBlock<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ImmutableBlock")
.field("block_id", &self.inner.block_id)
.field("sequence_hash", &self.inner.seq_hash)
.finish()
}
}
pub struct WeakBlock<T: BlockMetadata> {
sequence_hash: SequenceHash,
inner: Weak<ImmutableBlockInner<T>>,
handle: BlockRegistrationHandle,
store: Arc<BlockStore<T>>,
}
impl<T: BlockMetadata + Sync> WeakBlock<T> {
pub fn upgrade(&self) -> Option<ImmutableBlock<T>> {
if let Some(strong) = self.inner.upgrade() {
return Some(ImmutableBlock::from_inner(strong));
}
let inner = upgrade_or_resurrect::<T>(&self.handle, &self.store, false)?;
Some(ImmutableBlock::from_inner(inner))
}
pub fn sequence_hash(&self) -> SequenceHash {
self.sequence_hash
}
}
impl<T: BlockMetadata> Clone for WeakBlock<T> {
fn clone(&self) -> Self {
Self {
sequence_hash: self.sequence_hash,
inner: self.inner.clone(),
handle: self.handle.clone(),
store: self.store.clone(),
}
}
}
impl<T: BlockMetadata> std::fmt::Debug for WeakBlock<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("WeakBlock")
.field("sequence_hash", &self.sequence_hash)
.finish()
}
}