@@ -4066,102 +4066,154 @@ TermIndex installCheckpoint(String leaderId, Path checkpointLocation)
40664066
40674067 TermIndex installCheckpoint (String leaderId , Path checkpointLocation ,
40684068 TransactionInfo checkpointTrxnInfo ) throws Exception {
4069- OmRatisCheckpointInstaller .Context ctx = createCheckpointInstallContext ();
4070- OmRatisCheckpointInstaller installer = new OmRatisCheckpointInstaller ();
4071- return installer .installCheckpoint (ctx , leaderId , checkpointLocation ,
4072- checkpointTrxnInfo );
4073- }
4074-
4075- /**
4076- * Creates a context for checkpoint installation that provides access to
4077- * OzoneManager's internal operations without exposing private methods/fields.
4078- */
4079- private OmRatisCheckpointInstaller .Context createCheckpointInstallContext () {
4080- return new OmRatisCheckpointInstaller .Context () {
4081- @ Override
4082- public void stopBackgroundServicesAndPause () throws Exception {
4083- keyManager .stop ();
4084- stopSecretManager ();
4085- stopTrashEmptier ();
4086- omSnapshotManager .invalidateCache ();
4087- // Pause the State Machine so that no new transactions can be applied.
4088- // This action also clears the OM Double Buffer so that if there are any
4089- // pending transactions in the buffer, they are discarded.
4090- omRatisServer .getOmStateMachine ().pause ();
4091- }
4092-
4093- @ Override
4094- public void startBackgroundServices () throws Exception {
4095- keyManager .start (configuration );
4096- startSecretManagerIfNecessary ();
4097- startTrashEmptier (configuration );
4098- }
4099-
4100- @ Override
4101- public TermIndex getLastAppliedTermIndex () {
4102- return omRatisServer .getLastAppliedTermIndex ();
4103- }
4104-
4105- @ Override
4106- public File getCurrentDbLocation () {
4107- return metadataManager .getStore ().getDbLocation ();
4108- }
4109-
4110- @ Override
4111- public void stopRpcServer () {
4112- omRpcServer .stop ();
4113- isOmRpcServerRunning = false ;
4114- }
4069+ long startTime = Time .monotonicNow ();
4070+ File oldDBLocation = metadataManager .getStore ().getDbLocation ();
4071+ Path omDbPath = Paths .get (checkpointLocation .toString (), OM_DB_NAME );
4072+ try {
4073+ // Stop Background services
4074+ keyManager .stop ();
4075+ stopSecretManager ();
4076+ stopTrashEmptier ();
4077+ omSnapshotManager .invalidateCache ();
4078+ // Pause the State Machine so that no new transactions can be applied.
4079+ // This action also clears the OM Double Buffer so that if there are any
4080+ // pending transactions in the buffer, they are discarded.
4081+ omRatisServer .getOmStateMachine ().pause ();
4082+ } catch (Exception e ) {
4083+ LOG .error ("Failed to stop/ pause the services. Cannot proceed with " +
4084+ "installing the new checkpoint." );
4085+ // Stop the checkpoint install process and restart the services.
4086+ keyManager .start (configuration );
4087+ startSecretManagerIfNecessary ();
4088+ startTrashEmptier (configuration );
4089+ throw e ;
4090+ }
41154091
4116- @ Override
4117- public void stopMetadataManager () throws Exception {
4092+ File dbBackup = null ;
4093+ TermIndex termIndex = omRatisServer .getLastAppliedTermIndex ();
4094+ long term = termIndex .getTerm ();
4095+ long lastAppliedIndex = termIndex .getIndex ();
4096+
4097+ // Check if current applied log index is smaller than the downloaded
4098+ // checkpoint transaction index. If yes, proceed by stopping the ratis
4099+ // server so that the OM state can be re-initialized. If no then do not
4100+ // proceed with installSnapshot.
4101+ boolean canProceed = OzoneManagerRatisUtils .verifyTransactionInfo (
4102+ checkpointTrxnInfo , lastAppliedIndex , leaderId , omDbPath );
4103+
4104+ boolean oldOmMetadataManagerStopped = false ;
4105+ boolean newMetadataManagerStarted = false ;
4106+ boolean omRpcServerStopped = false ;
4107+ long time = Time .monotonicNow ();
4108+ if (canProceed ) {
4109+ // Stop RPC server before stop metadataManager
4110+ omRpcServer .stop ();
4111+ isOmRpcServerRunning = false ;
4112+ omRpcServerStopped = true ;
4113+ LOG .info ("RPC server is stopped. Spend {} ms." , Time .monotonicNow () - time );
4114+ try {
4115+ // Stop old metadataManager before replacing DB Dir
4116+ time = Time .monotonicNow ();
41184117 metadataManager .stop ();
4118+ oldOmMetadataManagerStopped = true ;
4119+ LOG .info ("metadataManager is stopped. Spend {} ms." , Time .monotonicNow () - time );
4120+ } catch (Exception e ) {
4121+ String errorMsg = "Failed to stop metadataManager. Cannot proceed " +
4122+ "with installing the new checkpoint." ;
4123+ LOG .error (errorMsg );
4124+ exitManager .exitSystem (1 , errorMsg , e , LOG );
41194125 }
4120-
4121- @ Override
4122- public void closeSnapshotManager () {
4123- omSnapshotManager .close ();
4124- }
4125-
4126- @ Override
4127- public void reloadOMState () throws IOException {
4128- OzoneManager .this .reloadOMState ();
4126+ try {
4127+ time = Time .monotonicNow ();
4128+ OmRatisCheckpointInstaller installer = new OmRatisCheckpointInstaller ();
4129+ dbBackup = installer .replaceOMDBWithCheckpoint (
4130+ lastAppliedIndex , oldDBLocation , checkpointLocation ,
4131+ getRatisLogDirectory ());
4132+ term = checkpointTrxnInfo .getTerm ();
4133+ lastAppliedIndex = checkpointTrxnInfo .getTransactionIndex ();
4134+ LOG .info ("Replaced DB with checkpoint from OM: {}, term: {}, " +
4135+ "index: {}, time: {} ms" , leaderId , term , lastAppliedIndex ,
4136+ Time .monotonicNow () - time );
4137+ } catch (Exception e ) {
4138+ LOG .error ("Failed to install Snapshot from {} as OM failed to replace" +
4139+ " DB with downloaded checkpoint. Reloading old OM state." ,
4140+ leaderId , e );
41294141 }
4142+ } else {
4143+ LOG .warn ("Cannot proceed with InstallSnapshot as OM is at TermIndex {} " +
4144+ "and checkpoint has lower TermIndex {}. Reloading old state of OM." ,
4145+ termIndex , checkpointTrxnInfo .getTermIndex ());
4146+ }
41304147
4131- @ Override
4132- public void setTransactionInfo ( TransactionInfo info ) {
4133- OzoneManager . this . setTransactionInfo ( info );
4134- }
4148+ if ( oldOmMetadataManagerStopped ) {
4149+ // Close snapDiff's rocksDB instance only if metadataManager gets closed.
4150+ omSnapshotManager . close ( );
4151+ }
41354152
4136- @ Override
4137- public void unpauseStateMachine (long index , long term ) {
4138- omRatisServer .getOmStateMachine ().unpause (index , term );
4153+ // Reload the OM DB store with the new checkpoint.
4154+ // Restart (unpause) the state machine and update its last applied index
4155+ // to the installed checkpoint's snapshot index.
4156+ try {
4157+ if (oldOmMetadataManagerStopped ) {
4158+ time = Time .monotonicNow ();
4159+ reloadOMState ();
4160+ setTransactionInfo (TransactionInfo .valueOf (termIndex ));
4161+ omRatisServer .getOmStateMachine ().unpause (lastAppliedIndex , term );
4162+ newMetadataManagerStarted = true ;
4163+ LOG .info ("Reloaded OM state with Term: {} and Index: {}. Spend {} ms" ,
4164+ term , lastAppliedIndex , Time .monotonicNow () - time );
4165+ } else {
4166+ // OM DB is not stopped. Start the services.
4167+ keyManager .start (configuration );
4168+ startSecretManagerIfNecessary ();
4169+ startTrashEmptier (configuration );
4170+ omRatisServer .getOmStateMachine ().unpause (lastAppliedIndex , term );
4171+ LOG .info ("OM DB is not stopped. Started services with Term: {} and " +
4172+ "Index: {}" , term , lastAppliedIndex );
41394173 }
4174+ } catch (Exception ex ) {
4175+ String errorMsg = "Failed to reload OM state and instantiate services." ;
4176+ exitManager .exitSystem (1 , errorMsg , ex , LOG );
4177+ }
41404178
4141- @ Override
4142- public void restartRpcServer () throws Exception {
4179+ if (omRpcServerStopped && newMetadataManagerStarted ) {
4180+ // Start the RPC server. RPC server start requires metadataManager
4181+ try {
4182+ time = Time .monotonicNow ();
41434183 omRpcServer = getRpcServer (configuration );
41444184 omRpcServer .start ();
41454185 isOmRpcServerRunning = true ;
4186+ LOG .info ("RPC server is re-started. Spend {} ms." , Time .monotonicNow () - time );
4187+ } catch (Exception e ) {
4188+ String errorMsg = "Failed to start RPC Server." ;
4189+ exitManager .exitSystem (1 , errorMsg , e , LOG );
41464190 }
4191+ }
4192+ buildDBCheckpointInstallAuditLog (leaderId , term , lastAppliedIndex );
41474193
4148- @ Override
4149- public void auditCheckpointInstall ( String leaderId , long term ,
4150- long lastAppliedIndex ) {
4151- buildDBCheckpointInstallAuditLog ( leaderId , term , lastAppliedIndex );
4194+ // Delete the backup DB
4195+ try {
4196+ if ( dbBackup != null ) {
4197+ FileUtils . deleteFully ( dbBackup );
41524198 }
4199+ } catch (Exception e ) {
4200+ LOG .error ("Failed to delete the backup of the original DB {}" ,
4201+ dbBackup , e );
4202+ }
41534203
4154- @ Override
4155- public void exitSystem ( int code , String msg , Exception e , Logger log )
4156- throws IOException {
4157- exitManager . exitSystem ( code , msg , e , log ) ;
4158- }
4204+ if ( lastAppliedIndex != checkpointTrxnInfo . getTransactionIndex ()) {
4205+ // Install Snapshot failed and old state was reloaded. Return null to
4206+ // Ratis to indicate that installation failed.
4207+ return null ;
4208+ }
41594209
4160- @ Override
4161- public String getRatisLogDirName () {
4162- return getRatisLogDirectory ();
4163- }
4164- };
4210+ // TODO: We should only return the snpashotIndex to the leader.
4211+ // Should be fixed after RATIS-586
4212+ TermIndex newTermIndex = TermIndex .valueOf (term , lastAppliedIndex );
4213+ LOG .info ("Install Checkpoint is finished with Term: {} and Index: {}. " +
4214+ "Spend {} ms." , newTermIndex .getTerm (), newTermIndex .getIndex (),
4215+ (Time .monotonicNow () - startTime ));
4216+ return newTermIndex ;
41654217 }
41664218
41674219 private void buildDBCheckpointInstallAuditLog (String leaderId , long term , long lastAppliedIndex ) {
0 commit comments