trine-kv 0.6.0

Embedded LSM MVCC key-value database.
Documentation
use std::{
    hash::{BuildHasher, Hash},
    path::PathBuf,
    sync::Arc,
    time::Duration,
};

use futures::lock::MutexGuard;
use sha2::Sha256;

use crate::{
    content::{
        CONTENT_CONTROL_BUCKET, CONTENT_LEASE_BUCKET, CONTENT_PHYSICAL_HOLD_BUCKET,
        CONTENT_TOKEN_BUCKET, CONTENT_TOKEN_INDEX_BUCKET, ContentAccessBarrier,
        ContentAccessBarrierId, ContentAccessBarrierRecord, ContentAccessCoordinateRecord,
        ContentAccessMode, ContentDescriptor, ContentHandle, ContentId, ContentLease,
        ContentLeaseId, ContentLeaseOptions, ContentLeaseRecord, ContentLifecycleMaintenanceReport,
        ContentPhysicalAccountRecord, ContentPhysicalHold, ContentPhysicalHoldId,
        ContentPhysicalHoldOptions, ContentPhysicalHoldOwnerId, ContentPhysicalHoldRecord,
        ContentPhysicalHoldRecordState, ContentPhysicalQuota, ContentPhysicalReservationRecord,
        ContentQuarantine, ContentQuarantineRecord, ContentReaderDrainAttestation,
        ContentReaderDrainAttestationId, ContentReaderDrainAttestationOptions,
        ContentReaderDrainAttestationRecord, ContentReclaimGrace, ContentReclaimGraceRecord,
        ContentReclaimSweep, ContentReclaimSweepBackend, ContentReclaimSweepRecord,
        ContentReclaimSweepRecordState, ContentTokenIndexRecord, ContentUpload, ContentUploadInfo,
        ContentUploadMaintenanceReport, ContentUploadOptions, ContentUploadResume, SealedContent,
        StorageDomainId, UploadId, UploadIdRetirement, UploadSessionState, UploadSessionStatus,
        UploadToken, UploadTokenRecord, content_access_coordinate_key, content_control_key,
        content_lease_key, content_lease_prefix, content_physical_account_key,
        content_physical_hold_key, content_physical_quota_key, content_physical_reservation_key,
        content_quarantine_key, content_reader_drain_attestation_key, content_reclaim_grace_key,
        content_reclaim_sweep_key, content_token_index_key, current_epoch_millis,
        decode_upload_id_tombstone, duration_millis, encode_upload_id_tombstone, upload_token_key,
    },
    error::{Error, Result},
    options::{
        ContentReclamationMode, DurabilityMode, HostStorageBackend, StorageMode, WriteOptions,
    },
    storage::{StorageObjectId, StorageObjectKind},
    transaction::TransactionOptions,
    types::KeyRange,
};

use super::Db;

fn initial_upload_reservation(state: &UploadSessionState) -> u64 {
    state
        .options()
        .expected_length()
        .unwrap_or_else(|| state.length())
}

fn content_lock_shard_index(
    hasher: &impl BuildHasher,
    id: &impl Hash,
    shard_count: usize,
) -> usize {
    debug_assert!(shard_count != 0);
    usize::try_from(hasher.hash_one(id) % shard_count as u64)
        .expect("content lock shard always fits usize")
}

mod backend;
mod lease_hold;
mod reclaim;
mod storage;
mod upload;

#[cfg(test)]
mod lock_shard_tests {
    use std::{
        collections::{BTreeSet, hash_map::RandomState},
        hash::{BuildHasherDefault, DefaultHasher},
    };

    use super::content_lock_shard_index;
    use crate::content::{StorageDomainId, UploadId};

    #[test]
    fn lock_sharding_hashes_the_complete_identifier() {
        let hasher = BuildHasherDefault::<DefaultHasher>::default();
        let upload_shards = (0_u8..=u8::MAX)
            .map(|suffix| {
                let mut bytes = [7_u8; 16];
                bytes[15] = suffix;
                content_lock_shard_index(&hasher, &UploadId::from_bytes(bytes), 256)
            })
            .collect::<BTreeSet<_>>();

        assert!(
            upload_shards.len() > 64,
            "IDs with one shared prefix must not collapse onto one lock"
        );
    }

    #[test]
    fn keyed_lock_sharding_is_stable_within_one_database() {
        let hasher = RandomState::new();
        let domain = StorageDomainId::from_bytes([19; 16]);

        assert_eq!(
            content_lock_shard_index(&hasher, &domain, 256),
            content_lock_shard_index(&hasher, &domain, 256)
        );
    }
}