/* * Copyright (c) 2009-2010 "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.onlinebackup.net; import org.neo4j.kernel.impl.transaction.xaframework.XaDataSource; import org.neo4j.onlinebackup.ha.AbstractSlave; public class ConnectToMasterJob extends ConnectionJob { private static enum Status implements JobStatus { SETUP_GREETING, SEND_GREETING, GET_RESPONSE, } private final AbstractSlave slave; private final String xaDsName; private final XaDataSource xaDs; private long masterVersion; private int retries = 0; public ConnectToMasterJob( Connection connection, AbstractSlave slave, String xaDsName, XaDataSource xaDs ) { super( connection, slave ); this.slave = slave; this.xaDsName = xaDsName; this.xaDs = xaDs; setStatus( Status.SETUP_GREETING ); } private boolean setupGreeting() { if ( retries > 20 ) { close(); } if ( !acquireWriteBuffer() ) { retries++; return false; } buffer.put( HeaderConstants.SLAVE_GREETING ); buffer.putLong( xaDs.getRandomIdentifier() ); buffer.putLong( xaDs.getCreationTime() ); buffer.putLong( xaDs.getCurrentLogVersion() ); byte[] bytes = xaDsName.getBytes(); buffer.putInt( bytes.length ); buffer.put( bytes ); 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(); setStatus( Status.GET_RESPONSE ); return true; } retries++; return false; } private boolean getResponse() { if ( retries > 20 ) { close(); } if ( !acquireReadBuffer() ) { retries++; return false; } try { // HEADER(1) + DB_VERISON(8) buffer.limit( 9 ); int read = connection.read(); log( "Get greeting response" ); if ( read == 1 || read == 9 ) { buffer.flip(); byte masterGreeting = buffer.get(); if ( masterGreeting == HeaderConstants.BYE ) { log( "Problem connecting to master " + connection + ". Got BYE." ); close(); return true; } else if ( masterGreeting != HeaderConstants.MASTER_GREETING ) { log( "Got unkown greeting[" + masterGreeting + "] from " + connection ); close(); } else if ( read != 9 ) { retries++; connection.pushBackAllReadData(); return false; } masterVersion = buffer.getLong(); log( "Got master version: " + masterVersion ); if ( masterVersion < xaDs.getCurrentLogVersion() ) { log( "Got wrong version [" + masterVersion + "]" ); close(); return true; } setNoRequeue(); setChainJob( new HandleMasterConnection( connection, slave, masterVersion, xaDs ) ); return true; } else { retries++; if ( read > 0 ) { connection.pushBackAllReadData(); } return false; } } finally { releaseReadBuffer(); } } @Override public boolean performJob() { switch ( (Status) getStatus() ) { case SETUP_GREETING: return setupGreeting(); case SEND_GREETING: return sendGreeting(); case GET_RESPONSE: return getResponse(); default: throw new IllegalStateException( "Unkown status: " + getStatus() ); } } @Override void connectionClosed() { System.out.println( "Connection closed " + connection ); } public long getMasterVersion() { return masterVersion; } }