@@ -106,6 +106,11 @@ enum Commands {
106
106
#[ clap( long, short) ]
107
107
verbose : bool ,
108
108
} ,
109
+ #[ clap( about = "Generate and upload a snapshot for a given generation or timestamp" ) ]
110
+ Snapshot {
111
+ #[ clap( long, short) ]
112
+ generation : Option < uuid:: Uuid > ,
113
+ } ,
109
114
}
110
115
111
116
async fn run ( ) -> Result < ( ) > {
@@ -273,6 +278,44 @@ async fn run() -> Result<()> {
273
278
"rm command cannot be run without parameters; see -h or --help for details"
274
279
) ,
275
280
} ,
281
+ Commands :: Snapshot { generation } => {
282
+ tokio:: fs:: create_dir_all ( & database_dir) . await ?;
283
+ let generation = if let Some ( gen) = generation {
284
+ gen
285
+ } else if let Some ( gen) = client. latest_generation_before ( None ) . await {
286
+ gen
287
+ } else {
288
+ println ! ( "no generation to snapshot found; nothing to do" ) ;
289
+ return Ok ( ( ) ) ;
290
+ } ;
291
+ // snapshots mark the state of the DB at the beginning of the generation, therefore
292
+ // snapshot at generation N is a final state of database at generation N-1. This can
293
+ // be later used for fast restore: restore from generation N = snapshot + all WAL frames
294
+ // from that generation.
295
+ let parent = if let Some ( parent) = client. get_dependency ( & generation) . await ? {
296
+ parent
297
+ } else {
298
+ println ! ( "cannot create a snapshot at the beginning of the generation {}: parent generation not found" , generation) ;
299
+ return Ok ( ( ) ) ;
300
+ } ;
301
+ client. restore ( Some ( parent. clone ( ) ) , None ) . await ?;
302
+ println ! (
303
+ "restored database at the start of generation {}: preparing snapshot..." ,
304
+ generation
305
+ ) ;
306
+ let db_path = PathBuf :: from ( & database) ;
307
+ if let Err ( e) = verify_db ( & db_path) {
308
+ println ! ( "Verification failed: {e}" ) ;
309
+ std:: process:: exit ( 1 )
310
+ } else {
311
+ println ! ( "verification succeeded" ) ;
312
+ client. set_generation ( generation. clone ( ) ) ;
313
+ client. snapshot_main_db_file ( true ) . await ?;
314
+ client. wait_until_snapshotted ( ) . await ?;
315
+ println ! ( "snapshot uploaded for generation: {}" , generation) ;
316
+ tokio:: fs:: remove_dir_all ( & database_dir) . await ?;
317
+ }
318
+ }
276
319
} ;
277
320
Ok ( ( ) )
278
321
}
0 commit comments