@@ -106,6 +106,11 @@ enum Commands {
106106 #[ clap( long, short) ]
107107 verbose : bool ,
108108 } ,
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+ } ,
109114}
110115
111116async fn run ( ) -> Result < ( ) > {
@@ -273,6 +278,44 @@ async fn run() -> Result<()> {
273278 "rm command cannot be run without parameters; see -h or --help for details"
274279 ) ,
275280 } ,
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+ }
276319 } ;
277320 Ok ( ( ) )
278321}
0 commit comments