package org.neo4j.onlinebackup.ha;
import java.io.IOException;
import java.util.Map;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.kernel.EmbeddedReadOnlyGraphDatabase;
import org.neo4j.kernel.impl.nioneo.store.UnderlyingStorageException;
import org.neo4j.kernel.impl.nioneo.xa.NeoStoreXaDataSource;
import org.neo4j.onlinebackup.net.Callback;
import org.neo4j.onlinebackup.net.ConnectToMasterJob;
import org.neo4j.onlinebackup.net.Connection;
import org.neo4j.onlinebackup.net.Job;
import org.neo4j.onlinebackup.net.JobEater;
import org.neo4j.onlinebackup.net.SocketException;
public class ReadOnlySlave implements Callback
{
private final EmbeddedReadOnlyGraphDatabase graphDb;
private final NeoStoreXaDataSource xaDs;
private final JobEater jobEater;
private final LogApplier logApplier;
private final String masterIp;
private final int masterPort;
private final Connection masterConnection;
private long masterVersion;
public ReadOnlySlave( String path, Map<String,String> params,
String masterIp, int masterPort )
{
this.graphDb = new EmbeddedReadOnlyGraphDatabase( path, params );
this.xaDs = (NeoStoreXaDataSource) graphDb.getConfig().getTxModule()
.getXaDataSourceManager().getXaDataSource( "nioneodb" );
this.xaDs.makeBackupSlave();
recover();
jobEater = new JobEater();
logApplier = new LogApplier( xaDs );
jobEater.start();
logApplier.start();
this.masterIp = masterIp;
this.masterPort = masterPort;
masterConnection = new Connection( masterIp, masterPort );
if ( !masterConnection.connected() )
{
if ( masterConnection.connectionRefused() )
{
throw new SocketException( "Connection to master[" + masterIp +
":" + masterPort + "] refused" );
}
}
jobEater.addJob( new ConnectToMasterJob( masterConnection, this ) );
}
private void recover()
{
long nextVersion = xaDs.getCurrentLogVersion();
while ( xaDs.hasLogicalLog( nextVersion ) )
{
try
{
xaDs.applyLog( xaDs.getLogicalLog( nextVersion ) );
}
catch ( IOException e )
{
throw new UnderlyingStorageException(
"Unable to recover slave to consistent state", e );
}
nextVersion++;
}
}
public boolean isConnectedToMaster()
{
return masterConnection.connected();
}
public GraphDatabaseService getGraphDbService()
{
return graphDb;
}
public String getMasterIp()
{
return masterIp;
}
public int getMasterPort()
{
return masterPort;
}
public void jobExecuted( Job job )
{
if ( job instanceof ConnectToMasterJob )
{
ConnectToMasterJob connectJob = (ConnectToMasterJob) job;
masterVersion = connectJob.getMasterVersion();
if ( masterVersion > getVersion() )
{
// request log versions
}
}
}
public long getIdentifier()
{
return xaDs.getRandomIdentifier();
}
public long getCreationTime()
{
return xaDs.getCreationTime();
}
public long getVersion()
{
return xaDs.getCurrentLogVersion();
}
public boolean hasLog( long version )
{
return xaDs.hasLogicalLog( version );
}
public String getLogName( long version )
{
return xaDs.getFileName( version );
}
public void shutdown()
{
jobEater.stopEating();
logApplier.stopApplyLogs();
graphDb.shutdown();
}
public void tryApplyNewLog()
{
long nextVersion = xaDs.getCurrentLogVersion();
while ( xaDs.hasLogicalLog( nextVersion ) )
{
logApplier.applyLog( nextVersion );
nextVersion++;
}
//
}
}