// Parse server string.
int separator = server.lastIndexOf(':');
String port = server.substring(separator + 1);
String hostname = server.substring(0, separator);
ProtocolSession localSession = null;
boolean error = false;
try
{
/*
* Open a socket connection to the next candidate.
*/
int intPort = Integer.parseInt(port);
InetSocketAddress serverAddr = new InetSocketAddress(
InetAddress.getByName(hostname), intPort);
Socket socket = new Socket();
socket.setReceiveBufferSize(1000000);
socket.setTcpNoDelay(true);
socket.connect(serverAddr, 500);
localSession = replSessionSecurity.createClientSession(server, socket,
ReplSessionSecurity.HANDSHAKE_TIMEOUT);
boolean isSslEncryption =
replSessionSecurity.isSslEncryption(server);
/*
* Send our ServerStartMsg.
*/
ServerStartMsg serverStartMsg = new ServerStartMsg(serverId, baseDn,
maxRcvWindow, heartbeatInterval, state,
ProtocolVersion.getCurrentVersion(), this.getGenerationID(),
isSslEncryption,
groupId);
localSession.publish(serverStartMsg);
/*
* Read the ReplServerStartMsg or ReplServerStartDSMsg that should come
* back.
*/
ReplicationMsg msg = localSession.receive();
if (debugEnabled())
{
debugInfo("In RB for " + baseDn +
"\nRB HANDSHAKE SENT:\n" + serverStartMsg.toString() +
"\nAND RECEIVED:\n" + msg.toString());
}
// Wrap received message in a server info object
replServerInfo = ReplicationServerInfo.newInstance(msg);
// Sanity check
String repDn = replServerInfo.getBaseDn();
if (!(this.baseDn.equals(repDn)))
{
Message message = ERR_DS_DN_DOES_NOT_MATCH.get(repDn.toString(),
this.baseDn);
logError(message);
error = true;
}
/*
* We have sent our own protocol version to the replication server.
* The replication server will use the same one (or an older one
* if it is an old replication server).
*/
protocolVersion = ProtocolVersion.minWithCurrent(
replServerInfo.getProtocolVersion());
localSession.setProtocolVersion(protocolVersion);
if (!isSslEncryption)
{
localSession.stopEncryption();
}
} catch (ConnectException e)
{
/*
* There was no server waiting on this host:port
* Log a notice and try the next replicationServer in the list
*/
if (!connectionError)
{
Message message = NOTE_NO_CHANGELOG_SERVER_LISTENING.get(server);
if (keepConnection) // Log error message only for final connection
{
// the error message is only logged once to avoid overflowing
// the error log
logError(message);
} else if (debugEnabled())
{
debugInfo(message.toString());
}
}
error = true;
} catch (Exception e)
{
if ((e instanceof SocketTimeoutException) && debugEnabled())
{
debugInfo("Timeout trying to connect to RS " + server +
" for dn: " + baseDn);
}
Message message = ERR_EXCEPTION_STARTING_SESSION_PHASE.get("1",
baseDn, server, e.getLocalizedMessage() +
stackTraceToSingleLineString(e));
if (keepConnection) // Log error message only for final connection
{
logError(message);
} else if (debugEnabled())
{
debugInfo(message.toString());
}
error = true;
}
// Close session if requested
if (!keepConnection || error)
{
if (localSession != null)
{
if (debugEnabled())
debugInfo("In RB, closing session after phase 1");
if (protocolVersion >= ProtocolVersion.REPLICATION_PROTOCOL_V4)
{
// V4 protocol introduces a StopMsg to properly end communications
if (!error)
{
try
{
localSession.publish(new StopMsg());
} catch (IOException ioe)
{
// Anyway, going to close session, so nothing to do
}
}
}
try
{
localSession.close();
} catch (IOException e)
{
// The session was already closed, just ignore.
}
localSession = null;