package org.neo4j.onlinebackup.net;
import org.neo4j.onlinebackup.ha.Master;
public class HandleIncommingSlaveJob extends ConnectionJob
{
private static enum Status implements JobStatus
{
GET_GREETING,
SETUP_GREETING,
SEND_GREETING,
SEND_BYE,
}
private final Master master;
private long slaveVersion;
private int retries = 0;
public HandleIncommingSlaveJob( Connection connection, Master master )
{
super( connection, master );
this.master = master;
setStatus( Status.GET_GREETING );
}
private boolean getGreeting()
{
if ( retries > 20 )
{
close();
}
if ( !acquireReadBuffer() )
{
return false;
}
try
{
// HEADER(1) + DB_ID(8) + DB_TIMESTAMP(8) + DB_VERISON(8)
buffer.limit( 25 );
int read = connection.read();
if ( read == 25 )
{
buffer.flip();
byte slaveGreeting = buffer.get();
if ( slaveGreeting != HeaderConstants.SLAVE_GREETING )
{
setStatus( Status.SEND_BYE );
return true;
}
long id = buffer.getLong();
long timestamp = buffer.getLong();
long version = buffer.getLong();
long masterId = master.getIdentifier();
long masterTimestamp = master.getCreationTime();
long masterVersion = master.getVersion();
if ( id != master.getIdentifier() ||
timestamp != master.getCreationTime() ||
version > master.getVersion() )
{
log( "Got wrong id/time/version [" + id + "/" + timestamp +
"/" + version + "]" + "[" + masterId + "/" +
masterTimestamp + "/" + masterVersion + "]" );
setStatus( Status.SEND_BYE );
return true;
}
log( "Got slave version[" + version + "]. I am version[" +
master.getVersion() + "]" );
slaveVersion = version;
setStatus( Status.SETUP_GREETING );
retries = 0;
return true;
}
else
{
retries++;
if ( read > 0 )
{
connection.pushBackAllReadData();
}
return false;
}
}
finally
{
releaseReadBuffer();
}
}
private boolean setupGreeting()
{
if ( retries > 20 )
{
close();
}
if ( !acquireWriteBuffer() )
{
retries++;
return false;
}
buffer.put( HeaderConstants.MASTER_GREETING );
buffer.putLong( master.getVersion() );
buffer.flip();
log( "Setup greeting" );
setStatus( Status.SEND_GREETING );
retries = 0;
return true;
}
private boolean sendGreeting()
{
if ( retries > 20 )
{
close();
}
log( "Send greeting" );
connection.write();
if ( !buffer.hasRemaining() )
{
releaseWriteBuffer();
setNoRequeue();
setChainJob( new HandleSlaveConnection( connection, master, slaveVersion ) );
return true;
}
retries++;
return false;
}
private boolean sendBye()
{
if ( retries > 20 )
{
close();
}
if ( !acquireWriteBuffer() )
{
retries++;
return false;
}
try
{
log( "Send bye" );
buffer.put( HeaderConstants.BYE );
buffer.flip();
connection.write();
return true;
}
finally
{
releaseWriteBuffer();
close();
}
}
@Override
public boolean performJob()
{
switch ( (Status) getStatus() )
{
case GET_GREETING: return getGreeting();
case SETUP_GREETING: return setupGreeting();
case SEND_GREETING: return sendGreeting();
case SEND_BYE: return sendBye();
default:
throw new IllegalStateException( "Unkown status: " +
getStatus() );
}
}
@Override
void connectionClosed()
{
System.out.println( "Connection closed " + connection );
}
}