use of com.linkedin.databus.core.ScnNotFoundException in project databus by linkedin.
the class RelayPullThread method doReadDataEvents.
protected void doReadDataEvents(ConnectionState curState) {
boolean debugEnabled = _log.isDebugEnabled();
boolean enqueueMessage = true;
try {
ChunkedBodyReadableByteChannel readChannel = curState.getReadChannel();
Checkpoint cp = curState.getCheckpoint();
curState.setRelayFellOff(false);
String remoteErrorName = RemoteExceptionHandler.getExceptionName(readChannel);
Throwable knownRemoteError = _remoteExceptionHandler.getException(readChannel);
if (null != knownRemoteError && knownRemoteError instanceof ScnNotFoundException) {
if (toTearConnAfterHandlingResponse()) {
tearConnectionAndEnqueuePickServer();
enqueueMessage = false;
} else {
curState.setRelayFellOff(true);
if (_retriesOnFallOff.getRemainingRetriesNum() > 0) {
_log.error("Got SCNNotFoundException. Retry (" + _retriesOnFallOff.getRetriesNum() + ") out of " + _retriesOnFallOff.getConfig().getMaxRetryNum());
curState.switchToPickServer();
} else {
enqueueMessage = onRelayFellOff(curState, cp, knownRemoteError);
}
}
} else if (null != remoteErrorName) {
if (toTearConnAfterHandlingResponse()) {
tearConnectionAndEnqueuePickServer();
enqueueMessage = false;
} else {
//remote processing error
_log.error("read events error: " + RemoteExceptionHandler.getExceptionMessage(readChannel));
curState.switchToStreamResponseError();
}
} else {
/*DispatcherState dispatchState = curState.getDispatcherState();
dispatchState.switchToDispatchEvents();
_dispatcherThread.addNewStateBlocking(dispatchState);*/
if (debugEnabled)
_log.debug("Sending events to buffer");
DbusEventsStatisticsCollector connCollector = _sourcesConn.getInboundEventsStatsCollector();
if (curState.isSCNRegress()) {
_log.info("SCN Regress requested !! Sending a SCN Regress Message to dispatcher. Curr Ckpt :" + curState.getCheckpoint());
DbusEvent regressEvent = getEventFactory().createSCNRegressEvent(new SCNRegressMessage(curState.getCheckpoint()));
writeEventToRelayDispatcher(curState, regressEvent, "SCN Regress Event from ckpt :" + curState.getCheckpoint());
curState.setSCNRegress(false);
}
UnifiedClientStats unifiedClientStats = _sourcesConn.getUnifiedClientStats();
if (unifiedClientStats != null) {
// failsafe: we're definitely not bootstrapping here
unifiedClientStats.setBootstrappingState(false);
sendHeartbeat(unifiedClientStats);
}
int eventsNum = curState.getDataEventsBuffer().readEvents(readChannel, curState.getListeners(), connCollector);
boolean resetConnection = false;
if (eventsNum > 0) {
_timeSinceEventsSec = System.currentTimeMillis();
cp.checkPoint();
} else {
// check how long it has been since we got some events
if (_remoteExceptionHandler.getPendingEventSize(readChannel) > curState.getDataEventsBuffer().getMaxReadBufferCapacity()) {
// The relay had a pending event that we can never accommodate. This is fatal error.
String err = "ReadBuffer max capacity(" + curState.getDataEventsBuffer().getMaxReadBufferCapacity() + ") is less than event size(" + _remoteExceptionHandler.getPendingEventSize(readChannel) + "). Increase databus.client.connectionDefaults.eventBuffer.maxEventSize and restart.";
_log.fatal(err);
enqueueMessage(LifecycleMessage.createSuspendOnErroMessage(new PendingEventTooLargeException(err)));
return;
} else {
if (_noEventsConnectionResetTimeSec > 0) {
// unless the feature is disabled (<=0)
resetConnection = (System.currentTimeMillis() - _timeSinceEventsSec) / 1000 > _noEventsConnectionResetTimeSec;
if (resetConnection) {
_timeSinceEventsSec = System.currentTimeMillis();
_log.warn("about to reset connection to relay " + curState.getServerInetAddress() + ", because there were no events for " + _noEventsConnectionResetTimeSec + "secs");
}
}
}
}
if (debugEnabled)
_log.debug("Events read: " + eventsNum);
// if it has been too long since we got non-empty responses - the relay may be stuck, try to reconnect
if (toTearConnAfterHandlingResponse() || resetConnection) {
tearConnectionAndEnqueuePickServer();
enqueueMessage = false;
} else {
curState.switchToStreamResponseDone();
resetServerRetries();
}
}
if (enqueueMessage)
enqueueMessage(curState);
} catch (InterruptedException ie) {
_log.warn("interrupted", ie);
curState.switchToStreamResponseError();
enqueueMessage(curState);
} catch (InvalidEventException e) {
_log.error("error reading events from server:" + e, e);
curState.switchToStreamResponseError();
enqueueMessage(curState);
} catch (RuntimeException e) {
_log.error("runtime error reading events from server: " + e, e);
curState.switchToStreamResponseError();
enqueueMessage(curState);
}
}
use of com.linkedin.databus.core.ScnNotFoundException in project databus by linkedin.
the class RelayPullThread method doPickRelay.
protected void doPickRelay(ConnectionState curState) {
int serversNum = _servers.size();
if (0 == serversNum) {
enqueueMessage(LifecycleMessage.createSuspendOnErroMessage(new DatabusException("No relays specified")));
return;
}
Random rng = new Random();
DatabusRelayConnection relayConn = null;
ServerInfo serverInfo = null;
int retriesLeft;
BackoffTimer originalCounter = _status.getRetriesCounter();
if (curState.isRelayFellOff())
_status.setRetriesCounter(_retriesOnFallOff);
while (null == relayConn && (retriesLeft = _status.getRetriesLeft()) >= 0 && !checkForShutdownRequest()) {
_log.info("picking a relay; retries left:" + retriesLeft + ", Backoff Timer :" + _status.getRetriesCounter() + ", Are we retrying because of SCNNotFoundException : " + curState.isRelayFellOff());
backoffOnPullError();
_curServerIdx = (_curServerIdx < 0) ? rng.nextInt(serversNum) : (_curServerIdx + 1) % serversNum;
Iterator<ServerInfo> setIter = _servers.iterator();
for (int i = 0; i <= _curServerIdx; ++i) serverInfo = setIter.next();
try {
relayConn = _sourcesConn.getRelayConnFactory().createRelayConnection(serverInfo, this, _remoteExceptionHandler);
_log.info("picked a relay:" + serverInfo.toSimpleString());
} catch (Exception e) {
_log.error("Unable to get connection to relay:" + serverInfo.toSimpleString(), e);
}
}
_status.setRetriesCounter(originalCounter);
if (!checkForShutdownRequest()) {
_curServer = serverInfo;
if (null == relayConn) {
if (_currentState.isRelayFellOff()) {
boolean enqueueMessage = false;
try {
enqueueMessage = onRelayFellOff(curState, curState.getCheckpoint(), new ScnNotFoundException("Retries on SCNNotFoundException exhausted !!"));
} catch (InterruptedException ie) {
_log.error("interrupted while processing onRelayFellOff", ie);
curState.switchToPickServer();
enqueueMessage(curState);
} catch (InvalidEventException e) {
_log.error("error trying to notify dispatcher of bootstrapping :" + e.getMessage(), e);
curState.switchToPickServer();
enqueueMessage(curState);
}
if (enqueueMessage)
enqueueMessage(curState);
} else {
// There are no retries left. Invoke an onError callback
try {
_log.info("Puller retries exhausted. Injecting an error event on dispatcher queue to invoke onError callback");
_remoteExceptionHandler.handleException(new PullerRetriesExhaustedException());
} catch (InterruptedException ie) {
_log.error("Interrupted while processing retries exhausted", ie);
} catch (InvalidEventException e) {
_log.error("Error trying to notify dispatcher of puller retries getting exhausted", e);
}
_log.error("Cannot find a relay");
}
} else {
DatabusRelayConnection oldRelayConn = curState.getRelayConnection();
if (null != oldRelayConn) {
resetConnectionAndSetFlag();
}
sendHeartbeat(_sourcesConn.getUnifiedClientStats());
_log.info("Relay Puller switching to request sources");
curState.switchToRequestSources(serverInfo, serverInfo.getAddress(), relayConn);
_lastOpenConnection = relayConn;
enqueueMessage(curState);
}
}
}
use of com.linkedin.databus.core.ScnNotFoundException in project databus by linkedin.
the class RemoteExceptionHandler method getException.
public Throwable getException(ChunkedBodyReadableByteChannel readChannel) {
Throwable remoteException = null;
String err = getExceptionName(readChannel);
if (null != err) {
// in theory, we shall be reading the actual exception from the read channel.
if (err.equalsIgnoreCase(ScnNotFoundException.class.getName())) {
remoteException = new ScnNotFoundException();
} else if (err.equalsIgnoreCase(BootstrapDatabaseTooOldException.class.getName())) {
remoteException = new BootstrapDatabaseTooOldException();
} else if (err.equalsIgnoreCase(PullerRetriesExhaustedException.class.getName())) {
remoteException = new PullerRetriesExhaustedException();
} else if (err.equalsIgnoreCase(BootstrapDatabaseTooYoungException.class.getName())) {
remoteException = new BootstrapDatabaseTooYoungException();
} else if (err.equalsIgnoreCase(BootstrapDBException.class.getName())) {
remoteException = new BootstrapDBException();
} else if (err.equalsIgnoreCase(SQLException.class.getName())) {
remoteException = new SQLException();
} else {
LOG.error("Unexpected remote error received: " + err);
}
LOG.info("Remote exception received: " + remoteException);
}
return remoteException;
}
use of com.linkedin.databus.core.ScnNotFoundException in project databus by linkedin.
the class ReadEventsRequestProcessor method process.
@Override
public DatabusRequest process(DatabusRequest request) throws IOException, RequestProcessingException, DatabusException {
boolean isDebug = LOG.isDebugEnabled();
try {
ObjectMapper objMapper = new ObjectMapper();
String checkpointString = request.getParams().getProperty(CHECKPOINT_PARAM, null);
String checkpointStringMult = request.getParams().getProperty(CHECKPOINT_PARAM_MULT, null);
int fetchSize = request.getRequiredIntParam(FETCH_SIZE_PARAM);
String formatStr = request.getRequiredStringParam(OUTPUT_FORMAT_PARAM);
Encoding enc = Encoding.valueOf(formatStr.toUpperCase());
String sourcesListStr = request.getParams().getProperty(SOURCES_PARAM, null);
String subsStr = request.getParams().getProperty(SUBS_PARAM, null);
String partitionInfoStr = request.getParams().getProperty(PARTITION_INFO_STRING);
String streamFromLatestSCNStr = request.getParams().getProperty(STREAM_FROM_LATEST_SCN);
String clientMaxEventVersionStr = request.getParams().getProperty(DatabusHttpHeaders.MAX_EVENT_VERSION);
int clientEventVersion = (clientMaxEventVersionStr != null) ? Integer.parseInt(clientMaxEventVersionStr) : DbusEventFactory.DBUS_EVENT_V1;
if (clientEventVersion < 0 || clientEventVersion == 1 || clientEventVersion > DbusEventFactory.DBUS_EVENT_V2) {
throw new InvalidRequestParamValueException(COMMAND_NAME, DatabusHttpHeaders.MAX_EVENT_VERSION, clientMaxEventVersionStr);
}
if (null == sourcesListStr && null == subsStr) {
throw new InvalidRequestParamValueException(COMMAND_NAME, SOURCES_PARAM + "|" + SUBS_PARAM, "null");
}
//TODO for now we separte the code paths to limit the impact on existing Databus 2 deployments (DDSDBUS-79)
//We have to get rid of this eventually and have a single data path.
boolean v2Mode = null == subsStr;
DbusKeyCompositeFilter keyCompositeFilter = null;
if (null != partitionInfoStr) {
try {
Map<Long, DbusKeyFilter> fMap = KeyFilterConfigJSONFactory.parseSrcIdFilterConfigMap(partitionInfoStr);
keyCompositeFilter = new DbusKeyCompositeFilter();
keyCompositeFilter.setFilterMap(fMap);
if (isDebug)
LOG.debug("keyCompositeFilter is :" + keyCompositeFilter);
} catch (Exception ex) {
String msg = "Got exception while parsing partition Configs. PartitionInfo is:" + partitionInfoStr;
LOG.error(msg, ex);
throw new InvalidRequestParamValueException(COMMAND_NAME, PARTITION_INFO_STRING, partitionInfoStr);
}
}
boolean streamFromLatestSCN = false;
if (null != streamFromLatestSCNStr) {
streamFromLatestSCN = Boolean.valueOf(streamFromLatestSCNStr);
}
long start = System.currentTimeMillis();
List<DatabusSubscription> subs = null;
//parse source ids
SourceIdNameRegistry srcRegistry = _relay.getSourcesIdNameRegistry();
HashSet<Integer> sourceIds = new HashSet<Integer>();
if (null != sourcesListStr) {
String[] sourcesList = sourcesListStr.split(",");
for (String sourceId : sourcesList) {
try {
Integer srcId = Integer.valueOf(sourceId);
sourceIds.add(srcId);
} catch (NumberFormatException nfe) {
HttpStatisticsCollector globalHttpStatsCollector = _relay.getHttpStatisticsCollector();
if (null != globalHttpStatsCollector) {
globalHttpStatsCollector.registerInvalidStreamRequest();
}
throw new InvalidRequestParamValueException(COMMAND_NAME, SOURCES_PARAM, sourceId);
}
}
}
//process explicit subscriptions and generate respective logical partition filters
NavigableSet<PhysicalPartitionKey> ppartKeys = null;
if (null != subsStr) {
List<DatabusSubscription.Builder> subsBuilder = null;
subsBuilder = objMapper.readValue(subsStr, new TypeReference<List<DatabusSubscription.Builder>>() {
});
subs = new ArrayList<DatabusSubscription>(subsBuilder.size());
for (DatabusSubscription.Builder subBuilder : subsBuilder) {
subs.add(subBuilder.build());
}
ppartKeys = new TreeSet<PhysicalPartitionKey>();
for (DatabusSubscription sub : subs) {
PhysicalPartition ppart = sub.getPhysicalPartition();
if (ppart.isAnyPartitionWildcard()) {
ppartKeys = _eventBuffer.getAllPhysicalPartitionKeys();
break;
} else {
ppartKeys.add(new PhysicalPartitionKey(ppart));
}
}
}
// Need to make sure that we don't have tests that send requests in this form.
if (subs != null && checkpointStringMult == null && checkpointString != null) {
throw new RequestProcessingException("Both Subscriptions and CheckpointMult should be present");
}
//convert source ids into subscriptions
if (null == subs)
subs = new ArrayList<DatabusSubscription>();
for (Integer srcId : sourceIds) {
LogicalSource lsource = srcRegistry.getSource(srcId);
if (lsource == null)
throw new InvalidRequestParamValueException(COMMAND_NAME, SOURCES_PARAM, srcId.toString());
if (isDebug)
LOG.debug("registry returns " + lsource + " for srcid=" + srcId);
DatabusSubscription newSub = DatabusSubscription.createSimpleSourceSubscription(lsource);
subs.add(newSub);
}
DbusFilter ppartFilters = null;
if (subs.size() > 0) {
try {
ppartFilters = _eventBuffer.constructFilters(subs);
} catch (DatabusException de) {
throw new RequestProcessingException("unable to generate physical partitions filters:" + de.getMessage(), de);
}
}
ConjunctionDbusFilter filters = new ConjunctionDbusFilter();
// Source filter comes first
if (v2Mode)
filters.addFilter(new SourceDbusFilter(sourceIds));
else if (null != ppartFilters)
filters.addFilter(ppartFilters);
/*
// Key range filter comes next
if ((keyMin >0) && (keyMax > 0))
{
filters.addFilter(new KeyRangeFilter(keyMin, keyMax));
}
*/
if (null != keyCompositeFilter) {
filters.addFilter(keyCompositeFilter);
}
// need to update registerStreamRequest to support Mult checkpoint TODO (DDSDBUS-80)
// temp solution
// 3 options:
// 1. checkpointStringMult not null - generate checkpoint from it
// 2. checkpointStringMult null, checkpointString not null - create empty CheckpointMult
// and add create Checkpoint(checkpointString) and add it to cpMult;
// 3 both are null - create empty CheckpointMult and add empty Checkpoint to it for each ppartition
PhysicalPartition pPartition;
Checkpoint cp = null;
CheckpointMult cpMult = null;
if (checkpointStringMult != null) {
try {
cpMult = new CheckpointMult(checkpointStringMult);
} catch (InvalidParameterSpecException e) {
LOG.error("Invalid CheckpointMult:" + checkpointStringMult, e);
throw new InvalidRequestParamValueException("stream", "CheckpointMult", checkpointStringMult);
}
} else {
// there is no checkpoint - create an empty one
cpMult = new CheckpointMult();
Iterator<Integer> it = sourceIds.iterator();
while (it.hasNext()) {
Integer srcId = it.next();
pPartition = _eventBuffer.getPhysicalPartition(srcId);
if (pPartition == null)
throw new RequestProcessingException("unable to find physical partitions for source:" + srcId);
if (checkpointString != null) {
cp = new Checkpoint(checkpointString);
} else {
cp = new Checkpoint();
cp.setFlexible();
}
cpMult.addCheckpoint(pPartition, cp);
}
}
if (isDebug)
LOG.debug("checkpointStringMult = " + checkpointStringMult + ";singlecheckpointString=" + checkpointString + ";CPM=" + cpMult);
// of the server context.
if (cpMult.getCursorPartition() == null) {
cpMult.setCursorPartition(request.getCursorPartition());
}
if (isDebug) {
if (cpMult.getCursorPartition() != null) {
LOG.debug("Using physical paritition cursor " + cpMult.getCursorPartition());
}
}
// for registerStreamRequest we need a single Checkpoint (TODO - fix it) (DDSDBUS-81)
if (cp == null) {
Iterator<Integer> it = sourceIds.iterator();
if (it.hasNext()) {
Integer srcId = it.next();
pPartition = _eventBuffer.getPhysicalPartition(srcId);
cp = cpMult.getCheckpoint(pPartition);
} else {
cp = new Checkpoint();
cp.setFlexible();
}
}
if (null != checkpointString && isDebug)
LOG.debug("About to stream from cp: " + checkpointString.toString());
HttpStatisticsCollector globalHttpStatsCollector = _relay.getHttpStatisticsCollector();
HttpStatisticsCollector connHttpStatsCollector = null;
if (null != globalHttpStatsCollector) {
connHttpStatsCollector = (HttpStatisticsCollector) request.getParams().get(globalHttpStatsCollector.getName());
}
if (null != globalHttpStatsCollector)
globalHttpStatsCollector.registerStreamRequest(cp, sourceIds);
StatsCollectors<DbusEventsStatisticsCollector> statsCollectors = _relay.getOutBoundStatsCollectors();
try {
DbusEventBufferBatchReadable bufRead = v2Mode ? _eventBuffer.getDbusEventBufferBatchReadable(sourceIds, cpMult, statsCollectors) : _eventBuffer.getDbusEventBufferBatchReadable(cpMult, ppartKeys, statsCollectors);
int eventsRead = 0;
int minPendingEventSize = 0;
StreamEventsResult result = null;
bufRead.setClientMaxEventVersion(clientEventVersion);
if (v2Mode) {
result = bufRead.streamEvents(streamFromLatestSCN, fetchSize, request.getResponseContent(), enc, filters);
eventsRead = result.getNumEventsStreamed();
minPendingEventSize = result.getSizeOfPendingEvent();
if (isDebug) {
LOG.debug("Process: streamed " + eventsRead + " from sources " + Arrays.toString(sourceIds.toArray()));
//can be used for debugging to stream from a cp
LOG.debug("CP=" + cpMult);
}
//if (null != statsCollectors) statsCollectors.mergeStatsCollectors();
} else {
result = bufRead.streamEvents(streamFromLatestSCN, fetchSize, request.getResponseContent(), enc, filters);
eventsRead = result.getNumEventsStreamed();
minPendingEventSize = result.getSizeOfPendingEvent();
if (isDebug)
LOG.debug("Process: streamed " + eventsRead + " with subscriptions " + subs);
cpMult = bufRead.getCheckpointMult();
if (cpMult != null) {
request.setCursorPartition(cpMult.getCursorPartition());
}
}
if (eventsRead == 0 && minPendingEventSize > 0) {
// Append a header to indicate to the client that we do have at least one event to
// send, but it is too large to fit into client's offered buffer.
request.getResponseContent().addMetadata(DatabusHttpHeaders.DATABUS_PENDING_EVENT_SIZE, minPendingEventSize);
LOG.debug("Returning 0 events but have pending event of size " + minPendingEventSize);
}
} catch (ScnNotFoundException snfe) {
if (null != globalHttpStatsCollector) {
globalHttpStatsCollector.registerScnNotFoundStreamResponse();
}
throw new RequestProcessingException(snfe);
} catch (OffsetNotFoundException snfe) {
LOG.error("OffsetNotFound", snfe);
if (null != globalHttpStatsCollector) {
globalHttpStatsCollector.registerScnNotFoundStreamResponse();
}
throw new RequestProcessingException(snfe);
}
if (null != connHttpStatsCollector) {
connHttpStatsCollector.registerStreamResponse(System.currentTimeMillis() - start);
globalHttpStatsCollector.merge(connHttpStatsCollector);
connHttpStatsCollector.reset();
} else if (null != globalHttpStatsCollector) {
globalHttpStatsCollector.registerStreamResponse(System.currentTimeMillis() - start);
}
} catch (InvalidRequestParamValueException e) {
HttpStatisticsCollector globalHttpStatsCollector = _relay.getHttpStatisticsCollector();
if (null != globalHttpStatsCollector) {
globalHttpStatsCollector.registerInvalidStreamRequest();
}
throw e;
}
return request;
}
use of com.linkedin.databus.core.ScnNotFoundException in project databus by linkedin.
the class DbusEventBufferWriter method run.
@Override
public //run in a thread please;
void run() {
_stop = false;
_expectedEvents = -1;
_count = 0;
try {
Checkpoint cp = new Checkpoint();
//is there anything from the checkpoint I can infer that it's end of stream? control message?
cp.setFlexible();
do {
int streamedEvents = 0;
StreamEventsArgs args = new StreamEventsArgs(_batchsize).setStatsCollector(_stats);
while ((streamedEvents = _buffer.streamEvents(cp, _channel, args).getNumEventsStreamed()) > 0) {
_count += streamedEvents;
}
//the writer hangs around - cannot count events; cp provides current window and window offset;
//and streamedEvents has the count of all events - not just data events
} while (!_stop && !endOfEvents());
} catch (ScnNotFoundException e) {
LOG.error("SCN not found! " + e);
} catch (OffsetNotFoundException e) {
LOG.error("Offset not found! " + e);
} finally {
_stop = false;
}
}
Aggregations