@@ -89,6 +89,9 @@ pub struct Rebuild {
8989 /// for this key. If it exists, the data will be reconstructed according to the new policy,
9090 /// and the old metadata is replaced with the new metadata.
9191 pub key : Option < String > ,
92+
93+ /// metadata of the file/key to rebuild
94+ pub metadata : Option < MetaData > ,
9295}
9396
9497#[ derive( Serialize , Deserialize , Debug , Message , Clone ) ]
@@ -285,6 +288,7 @@ impl Handler<Rebuild> for ZstorActor {
285288 let pipeline = self . pipeline . clone ( ) ;
286289 let config = self . cfg . clone ( ) ;
287290 let meta = self . meta . clone ( ) ;
291+
288292 AtomicResponse :: new ( Box :: pin (
289293 async move {
290294 let cfg = config. send ( GetConfig ) . await ?;
@@ -300,31 +304,41 @@ impl Handler<Rebuild> for ZstorActor {
300304 std:: io:: Error :: from ( std:: io:: ErrorKind :: InvalidInput ) ,
301305 ) ) ;
302306 }
303- let old_metadata = if let Some ( ref file) = msg. file {
304- meta. send ( LoadMeta { path : file. clone ( ) } )
307+
308+ let old_metadata = match ( msg. metadata , & msg. file , & msg. key ) {
309+ ( Some ( metadata) , _, _) => {
310+ debug ! (
311+ "Using provided metadata for rebuild file:{:?} key: {:?}" ,
312+ & msg. file, & msg. key
313+ ) ;
314+ metadata
315+ }
316+ ( None , Some ( file) , _) => meta
317+ . send ( LoadMeta { path : file. clone ( ) } )
305318 . await ??
306319 . ok_or_else ( || {
307320 ZstorError :: new_io (
308321 "no metadata found for file" . to_string ( ) ,
309322 std:: io:: Error :: from ( std:: io:: ErrorKind :: NotFound ) ,
310323 )
311- } ) ?
312- } else if let Some ( ref key) = msg. key {
313- // key is set so the unwrap is safe
314- meta. send ( LoadMetaByKey { key : key. clone ( ) } )
324+ } ) ?,
325+ ( None , None , Some ( key) ) => meta
326+ . send ( LoadMetaByKey { key : key. clone ( ) } )
315327 . await ??
316328 . ok_or_else ( || {
317329 ZstorError :: new_io (
318330 "no metadata found for file" . to_string ( ) ,
319331 std:: io:: Error :: from ( std:: io:: ErrorKind :: NotFound ) ,
320332 )
321- } ) ?
322- } else {
323- unreachable ! ( ) ;
333+ } ) ?,
334+ _ => unreachable ! ( ) ,
324335 } ;
325336
337+ // load the data from the storage backends
326338 let input = load_data ( & old_metadata) . await ?;
327339 let existing_data = input. clone ( ) ;
340+
341+ // rebuild the data (in memory only)
328342 let ( mut metadata, shards) = pipeline
329343 . send ( RebuildData {
330344 input,
@@ -333,7 +347,9 @@ impl Handler<Rebuild> for ZstorActor {
333347 } )
334348 . await ??;
335349
336- // build a list of the key and the backend used for the shards
350+ // build a list of (key, backend used for the shards)
351+ // - if the shard still exists in the backend, we set the backend to the old backend
352+ // - if the shard is missing, we set the backend to None
337353 let mut used_backends = Vec :: new ( ) ;
338354 for ( i, data) in existing_data. iter ( ) . enumerate ( ) {
339355 let key = old_metadata. shards ( ) [ i] . key ( ) . to_vec ( ) ;
@@ -510,6 +526,8 @@ async fn check_backend_space(
510526 }
511527}
512528
529+ // Find valid backends for the shards
530+ // if the backend is part of the skip_backends, we don't need to check it again
513531async fn find_valid_backends (
514532 cfg : & mut Config ,
515533 shard_len : usize ,
0 commit comments