1 use std
::future
::Future
;
2 use std
::collections
::HashMap
;
4 use std
::sync
::{Arc, Mutex}
;
8 use super::BackupReader
;
9 use crate::backup
::{AsyncReadChunk, CryptConfig, DataBlob, ReadChunk}
;
10 use crate::tools
::runtime
::block_on
;
12 /// Read chunks from remote host using ``BackupReader``
14 pub struct RemoteChunkReader
{
15 client
: Arc
<BackupReader
>,
16 crypt_config
: Option
<Arc
<CryptConfig
>>,
17 cache_hint
: HashMap
<[u8; 32], usize>,
18 cache
: Arc
<Mutex
<HashMap
<[u8; 32], Vec
<u8>>>>,
21 impl RemoteChunkReader
{
22 /// Create a new instance.
24 /// Chunks listed in ``cache_hint`` are cached and kept in RAM.
26 client
: Arc
<BackupReader
>,
27 crypt_config
: Option
<Arc
<CryptConfig
>>,
28 cache_hint
: HashMap
<[u8; 32], usize>,
34 cache
: Arc
::new(Mutex
::new(HashMap
::new())),
38 pub async
fn read_raw_chunk(&self, digest
: &[u8; 32]) -> Result
<DataBlob
, Error
> {
39 let mut chunk_data
= Vec
::with_capacity(4 * 1024 * 1024);
42 .download_chunk(&digest
, &mut chunk_data
)
45 let chunk
= DataBlob
::load_from_reader(&mut &chunk_data
[..])?
;
47 // fixme: verify digest?
53 impl ReadChunk
for RemoteChunkReader
{
54 fn read_raw_chunk(&self, digest
: &[u8; 32]) -> Result
<DataBlob
, Error
> {
55 block_on(Self::read_raw_chunk(self, digest
))
58 fn read_chunk(&self, digest
: &[u8; 32]) -> Result
<Vec
<u8>, Error
> {
59 if let Some(raw_data
) = (*self.cache
.lock().unwrap()).get(digest
) {
60 return Ok(raw_data
.to_vec());
63 let chunk
= ReadChunk
::read_raw_chunk(self, digest
)?
;
65 let raw_data
= chunk
.decode(self.crypt_config
.as_ref().map(Arc
::as_ref
), Some(digest
))?
;
67 let use_cache
= self.cache_hint
.contains_key(digest
);
69 (*self.cache
.lock().unwrap()).insert(*digest
, raw_data
.to_vec());
76 impl AsyncReadChunk
for RemoteChunkReader
{
77 fn read_raw_chunk
<'a
>(
80 ) -> Pin
<Box
<dyn Future
<Output
= Result
<DataBlob
, Error
>> + Send
+ 'a
>> {
81 Box
::pin(Self::read_raw_chunk(self, digest
))
87 ) -> Pin
<Box
<dyn Future
<Output
= Result
<Vec
<u8>, Error
>> + Send
+ 'a
>> {
89 if let Some(raw_data
) = (*self.cache
.lock().unwrap()).get(digest
) {
90 return Ok(raw_data
.to_vec());
93 let chunk
= Self::read_raw_chunk(self, digest
).await?
;
95 let raw_data
= chunk
.decode(self.crypt_config
.as_ref().map(Arc
::as_ref
), Some(digest
))?
;
97 let use_cache
= self.cache_hint
.contains_key(digest
);
99 (*self.cache
.lock().unwrap()).insert(*digest
, raw_data
.to_vec());