/**
* Copyright (c) 2002-2011 "Neo Technology,"
* Network Engine for Objects in Lund AB [http://neotechnology.com]
*
* This file is part of Neo4j.
*
* Neo4j is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.neo4j.kernel.ha.zookeeper;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher.Event.KeeperState;
import org.apache.zookeeper.ZooKeeper;
public class ClusterManager extends AbstractZooKeeperManager
{
private final ZooKeeper zooKeeper;
private String rootPath;
private KeeperState state = KeeperState.Disconnected;
public ClusterManager( String zooKeeperServers )
{
super( zooKeeperServers, null );
this.zooKeeper = instantiateZooKeeper();
}
@Override
protected int getMyMachineId()
{
throw new UnsupportedOperationException("Not implemented ClusterManager.getMyMachineId()");
}
public void waitForSyncConnected()
{
long startTime = System.currentTimeMillis();
while ( System.currentTimeMillis()-startTime < SESSION_TIME_OUT )
{
if ( state == KeeperState.SyncConnected )
{
// We are connected
break;
}
try
{
Thread.sleep( 100 );
}
catch ( InterruptedException e )
{
Thread.interrupted();
}
}
}
public void process( WatchedEvent event )
{
// System.out.println( "Got event: " + event );
String path = event.getPath();
if ( path == null )
{
state = event.getState();
}
}
public Machine getMaster()
{
return getMasterBasedOn( getAllMachines( true ).values() );
}
@Override
public String getRoot()
{
if ( rootPath == null )
{
rootPath = readRootPath();
}
return rootPath;
}
private String readRootPath()
{
waitForSyncConnected();
String result = getSingleRootPath( getZooKeeper() );
if ( result == null )
{
throw new RuntimeException( "No root child found in zoo keeper" );
}
return result;
}
public static String getSingleRootPath( ZooKeeper keeper )
{
try
{
List<String> children = keeper.getChildren( "/", false );
String foundChild = null;
for ( String child : children )
{
if ( child.contains( "_" ) )
{
if ( foundChild != null )
{
throw new RuntimeException( "Multiple roots found, " +
foundChild + " and " + child );
}
foundChild = child;
}
}
if ( foundChild != null )
{
return "/" + foundChild;
}
return null;
}
catch ( KeeperException e )
{
throw new RuntimeException( e );
}
catch ( InterruptedException e )
{
throw new RuntimeException( e );
}
}
/**
* Returns the disconnected slaves in this cluster so that all slaves
* which are specified in the HA servers configuration, but not in the
* zoo keeper cluster will be returned.
* @return the disconnected slaves in this cluster.
*/
// public Machine[] getDisconnectedSlaves()
// {
// Collection<Machine> infos = new ArrayList<Machine>();
// for ( Map.Entry<Integer, String> entry : haServers.entrySet() )
// {
// infos.add( new Machine( entry.getKey(), -1, -1, entry.getValue() ) );
// }
// infos.removeAll( getAllMachines().values() );
// return infos.toArray( new Machine[infos.size()] );
// }
/**
* Returns the connected slaves in this cluster.
* @return the connected slaves in this cluster.
*/
public Machine[] getConnectedSlaves()
{
Map<Integer, Machine> machines = getAllMachines( true );
Machine master = getMasterBasedOn( machines.values() );
Collection<Machine> result = new ArrayList<Machine>( machines.values() );
result.remove( master );
return result.toArray( new Machine[result.size()] );
}
@Override
protected ZooKeeper getZooKeeper()
{
return this.zooKeeper;
}
}