boolean enqueueMessage = true;
try
{
Checkpoint cp = curState.getCheckpoint();
DbusEventBuffer eventBuffer = curState.getDataEventsBuffer();
if (debugEnabled) _log.debug("Sending bootstrap events to buffer");
//eventBuffer.startEvents();
DbusEventInternalReadable cpEvent = getEventFactory().createCheckpointEvent(cp);
byte[] cpEventBytes = new byte[cpEvent.size()];
if (debugEnabled)
{
_log.debug("checkpoint event size: " + cpEventBytes.length);
_log.debug("checkpoint event:" + cpEvent.toString());
}
cpEvent.getRawBytes().get(cpEventBytes);
ByteArrayInputStream cpIs = new ByteArrayInputStream(cpEventBytes);
ReadableByteChannel cpRbc = Channels.newChannel(cpIs);
UnifiedClientStats unifiedClientStats = _sourcesConn.getUnifiedClientStats();
sendHeartbeat(unifiedClientStats);
int ecnt = eventBuffer.readEvents(cpRbc);
success = (ecnt > 0);
if (!success)
{
_log.error("Unable to write bootstrap phase marker");
} else {
ChunkedBodyReadableByteChannel readChannel = curState.getReadChannel();
String remoteErrorName = RemoteExceptionHandler.getExceptionName(readChannel);
Throwable remoteError = _remoteExceptionHandler.getException(readChannel);
if (null != remoteError &&
remoteError instanceof BootstrapDatabaseTooOldException)
{
_log.error("Bootstrap database is too old!");
_remoteExceptionHandler.handleException(remoteError);
curState.switchToStreamResponseError();
}
else if (null != remoteErrorName)
{
//remote processing error
_log.error("read events error: " + RemoteExceptionHandler.getExceptionMessage(readChannel));
curState.switchToStreamResponseError();
}
else
{
sendHeartbeat(unifiedClientStats);
int eventsNum = eventBuffer.readEvents(readChannel, curState.getListeners(),
_sourcesConn.getBootstrapEventsStatsCollector());
if (eventsNum == 0 &&
_remoteExceptionHandler.getPendingEventSize(readChannel) > eventBuffer.getMaxReadBufferCapacity())
{
String err = "ReadBuffer max capacity(" + eventBuffer.getMaxReadBufferCapacity() +
") is less than event size(" +
_remoteExceptionHandler.getPendingEventSize(readChannel) +
"). Increase databus.client.connectionDefaults.bstEventBuffer.maxEventSize and restart.";
_log.fatal(err);
enqueueMessage(LifecycleMessage.createSuspendOnErroMessage(new PendingEventTooLargeException(err)));
return;
}
else
{
resetServerRetries();
if (debugEnabled) _log.debug("Sending events to buffer");
numEventsInCurrentState += eventsNum;
_log.info("Bootstrap events read so far: " + numEventsInCurrentState);
String status = readChannel.getMetadata("PhaseCompleted");
final BootstrapCheckpointHandler ckptHandler = curState.getBstCheckpointHandler();
if (status != null)
{ // set status in checkpoint to indicate that we are done with the current source
if (cp.getConsumptionMode() == DbusClientMode.BOOTSTRAP_CATCHUP)
{
ckptHandler.finalizeCatchupPhase(cp);
}
else if (cp.getConsumptionMode() == DbusClientMode.BOOTSTRAP_SNAPSHOT)
{
ckptHandler.finalizeSnapshotPhase(cp);
}
else
{
throw new RuntimeException("Invalid bootstrap phase: " + cp.getConsumptionMode());
}
_log.info("Bootstrap events read :" + numEventsInCurrentState + " during phase:"
+ cp.getConsumptionMode() + " [" + cp.getBootstrapSnapshotSourceIndex()
+ "," + cp.getBootstrapCatchupSourceIndex() + "]");
numEventsInCurrentState = 0;
}
else
{ // keep on reading more for the given snapshot
// question: how is snapshotOffset maintained in ckpt
if (eventsNum > 0)
{
cp.bootstrapCheckPoint();
}
}
curState.switchToStreamResponseDone();
}