private void doTransition ( List < StorageDirectory > sds , NamespaceInfo nsInfo , StartupOption startOpt ) throws IOException { if ( startOpt == StartupOption . ROLLBACK ) doRollback ( nsInfo ) ; // rollback if applicable int numOfDirs = sds . size ( ) ; List < StorageDirectory > dirsToUpgrade = new ArrayList < StorageDirectory > ( numOfDirs ) ; List < StorageInfo > dirsInfo = new ArrayList < StorageInfo > ( numOfDirs ) ; for ( StorageDirectory sd : sds ) { sd . read ( ) ; layoutMap . put ( sd . getRoot ( ) , this . layoutVersion ) ; checkVersionUpgradable ( this . layoutVersion ) ; assert this . layoutVersion >= FSConstants . LAYOUT_VERSION : "Future version is not allowed" ; boolean federationSupported = this . layoutVersion <= FSConstants . FEDERATION_VERSION ; // For pre-federation version - validate the namespaceID if ( ! federationSupported && getNamespaceID ( ) != nsInfo . getNamespaceID ( ) ) { sd . unlock ( ) ; throw new IOException ( "Incompatible namespaceIDs in " + sd . getRoot ( ) . getCanonicalPath ( ) + ": namenode namespaceID = " + nsInfo . getNamespaceID ( ) + "; datanode namespaceID = " + getNamespaceID ( ) ) ; } if ( this . layoutVersion == FSConstants . LAYOUT_VERSION && this . cTime == nsInfo . getCTime ( ) ) continue ; // regular startup // verify necessity of a distributed upgrade verifyDistributedUpgradeProgress ( nsInfo ) ; // do a global upgrade iff layout version changes and current layout is // older than FEDERATION. if ( this . layoutVersion > FSConstants . LAYOUT_VERSION && this . layoutVersion > FSConstants . FEDERATION_VERSION ) { if ( isNsLevelUpgraded ( getNamespaceID ( ) , sd ) ) { throw new IOException ( "Ns level directory already upgraded for : " + sd . getRoot ( ) + " ignoring upgrade" ) ; } dirsToUpgrade . add ( sd ) ; // upgrade dirsInfo . add ( new StorageInfo ( this ) ) ; continue ; } if ( this . cTime >= nsInfo . getCTime ( ) ) { // layoutVersion == LAYOUT_VERSION && this.cTime > nsInfo.cTime // must shutdown sd . unlock ( ) ; throw new IOException ( "Datanode state: LV = " + this . getLayoutVersion ( ) + " CTime = " + this . getCTime ( ) + " is newer than the namespace state: LV = " + nsInfo . getLayoutVersion ( ) + " CTime = " + nsInfo . getCTime ( ) ) ; } } // Now do upgrade if dirsToUpgrade is not empty if ( ! dirsToUpgrade . isEmpty ( ) ) { doUpgrade ( dirsToUpgrade , dirsInfo , nsInfo ) ; } }
Analyze which and whether a transition of the fs state is required and perform it if necessary .