@ Override protected void postInit ( ) throws Exception { if ( controlTree == null ) { throw new RuntimeException ( "controlTree not set" ) ; } controlTree . create ( NODES , false ) ; controlTree . create ( LEADERS , false ) ; if ( controlTree . exists ( myNodeInfo . treeNodePath ) ) { LOG . error ( "A node with the name " + myNodeInfo . getName ( ) + " already exists!" ) ; throw new RuntimeException ( "Initialization failure" ) ; } LOG . info ( "Required peer node properties: {}" , requiredPeerNodeProperties ) ; LOG . info ( "Required server properties: {}" , requiredServerProperties ) ; final Set < String > requiredProperties = ( myId == 0 ? requiredServerProperties : requiredPeerNodeProperties ) ; for ( String property : requiredProperties ) { if ( ! property . equals ( "id" ) && myNodeInfo . get ( property ) == null ) { LOG . error ( "Required property {} not set!" , property ) ; throw new RuntimeException ( "Initialization failure" ) ; } } /// the calls in the demarcated section need to be in this specific order to avoid a possible race between nodes and leaders // `>>>> BEGIN CAREFULLY ORDERED SECTION branch = new DistributedBranchHelper ( controlTree , NODES , false ) { @ Override protected boolean isNodeComplete ( String node , Set < String > properties ) { if ( ! properties . contains ( "id" ) ) { return false ; } final short id = Short . parseShort ( new String ( controlTree . get ( node + "/id" ) , Charsets . UTF_8 ) ) ; final Set < String > requiredProperties = ( id == 0 ? requiredServerProperties : requiredPeerNodeProperties ) ; final boolean success = properties . containsAll ( requiredProperties ) ; return success ; } } ; branch . addListener ( new DistributedTree . ListenerAdapter ( ) { @ Override public void nodeChildAdded ( String parentPath , String childName ) { AbstractCluster . this . nodeAdded ( childName ) ; } @ Override public void nodeChildDeleted ( String parentPath , String childName ) { AbstractCluster . this . nodeRemoved ( childName ) ; } } ) ; // This read and handles the nodes. branch . init ( ) ; controlTree . addListener ( LEADERS , new DistributedTree . ListenerAdapter ( ) { @ Override public void nodeChildAdded ( String parentPath , String childName ) { AbstractCluster . this . leaderAdded ( childName ) ; } @ Override public void nodeChildDeleted ( String parentPath , String childName ) { AbstractCluster . this . leaderRemoved ( childName ) ; } } ) ; myNodeInfo . writeToTree ( ) ; setReady ( true ) ; super . postInit ( ) ; joined = true ; fireJoinedCluster ( ) ; for ( short id : masters . keySet ( ) ) { if ( id != myId ) fireNodeAdded ( id ) ; } }
This is perhaps ugly but overriding implementations must call this method at the end or at least after calling setControlTree