block_db/
read.rs

1// Authors: Robert Lopez
2
3use super::{error::Error, BlockDB, BlockKey};
4use std::collections::HashMap;
5
6impl BlockDB {
7    /// Reads the bytes of a `DataBlock` from a `DataFile`.
8    ///
9    /// Returns `None` if either the `data_file_id` or `data_block_id` does not exist.
10    ///
11    /// ---
12    /// - **Atomic**
13    /// - **Non-corruptible**
14    ///
15    /// ---
16    /// Example
17    /// ``` let block_db = BlockDB::open("./data", None).await?;
18    ///
19    /// // BlockKey { data_file_id, data_block_id }
20    /// let block_key = block_db.write(b"Hello World").await?;
21    ///
22    /// // b"Hello World".to_vec()
23    /// let data = block_db.read(&block_key).await?.unwrap();
24    /// ```
25    /// ---
26    pub async fn read(
27        &self,
28        BlockKey {
29            data_file_id,
30            data_block_id,
31        }: &BlockKey,
32    ) -> Result<Option<Vec<u8>>, Error> {
33        if let Some(data_file) = self.data_files.read().await.get(data_file_id).cloned() {
34            return data_file.write().await.read(data_block_id).await;
35        }
36
37        Ok(None)
38    }
39
40    /// Reads the bytes of multiple `DataBlock`s in a single, consistent view.
41    ///
42    /// ---
43    /// - **Atomic**
44    /// - **Non-corruptible**
45    ///
46    /// ---
47    /// Example
48    /// ``` let block_db = BlockDB::open("./data", None).await?;
49    ///
50    /// let block_key_one = block_db.write(b"Hello").await?;
51    /// let block_key_two = block_db.write(b"World").await?;
52    ///
53    /// // {
54    /// //   BlockKey { .. } : Some(b"Hello"),
55    /// //   BlockKey { .. } : Some(b"World"),
56    /// // }
57    /// let read_many_map = block_db.read_many(vec![&block_key_one, &block_key_two]).await?;
58    /// ```
59    /// ---
60    pub async fn read_many(
61        &self,
62        keys: Vec<&BlockKey>,
63    ) -> Result<HashMap<BlockKey, Option<Vec<u8>>>, Error> {
64        let data_files = self.data_files.read().await.clone();
65        let mut data_file_locks = HashMap::new();
66
67        for BlockKey { data_file_id, .. } in keys.iter() {
68            if !data_file_locks.contains_key(data_file_id) {
69                if let Some(data_file) = data_files.get(data_file_id) {
70                    data_file_locks.insert(data_file_id, data_file.write().await);
71                }
72            }
73        }
74
75        let mut data_blocks_map = HashMap::new();
76
77        for block_key in keys {
78            if let Some(data_file_lock) = data_file_locks.get_mut(&block_key.data_file_id) {
79                data_blocks_map.insert(
80                    block_key.clone(),
81                    data_file_lock.read(&block_key.data_block_id).await?,
82                );
83            } else {
84                data_blocks_map.insert(block_key.clone(), None);
85            }
86        }
87
88        Ok(data_blocks_map)
89    }
90}