}
protected boolean internalRun() {
if (log.isDebugEnabled()) log.debug("Enter: Sender::internalRun");
Transaction transaction = null;
boolean sleep = false;
try {
// Pick a sequence using a round-robin approach
ArrayList allSequencesList = getSequences();
int size = allSequencesList.size();
if (log.isDebugEnabled())
log.debug("Choosing one from " + size + " sequences");
if(nextIndex >= size) {
nextIndex = 0;
// We just looped over the set of sequences. If we didn't process any
// messages on this loop then we sleep before the next one
if(size == 0 || !processedMessage) {
sleep = true;
}
processedMessage = false;
// At this point - delete any sequences that have timed out, or been terminated.
deleteTerminatedSequences(storageManager);
// Also clean up and sender beans that are not yet eligible for sending, but
// are blocking the transport threads.
unblockTransportThreads(storageManager);
// Finally, check for messages that can only be serviced by polling, and warn
// the user if they are too old
checkForOrphanMessages(storageManager);
if (log.isDebugEnabled()) log.debug("Exit: Sender::internalRun, looped over all sequences, sleep " + sleep);
return sleep;
}
SequenceEntry entry = (SequenceEntry) allSequencesList.get(nextIndex++);
String sequenceId = entry.getSequenceId();
if (log.isDebugEnabled())
log.debug("Chose sequence " + sequenceId);
transaction = storageManager.getTransaction();
String rmVersion = null;
// Check that the sequence is still valid
boolean found = false;
if(entry.isRmSource()) {
RMSBean matcher = new RMSBean();
matcher.setInternalSequenceID(sequenceId);
matcher.setTerminated(false);
RMSBean rms = storageManager.getRMSBeanMgr().findUnique(matcher);
if(rms != null && !rms.isTerminated() && !rms.isTimedOut()) {
sequenceId = rms.getSequenceID();
if (SequenceManager.hasSequenceTimedOut(rms, sequenceId, storageManager))
SequenceManager.finalizeTimedOutSequence(rms.getInternalSequenceID(), null, storageManager);
else
found = true;
rmVersion = rms.getRMVersion();
}
} else {
RMDBean matcher = new RMDBean();
matcher.setSequenceID(sequenceId);
matcher.setTerminated(false);
RMDBean rmd = storageManager.getRMDBeanMgr().findUnique(matcher);
if(rmd != null) {
found = true;
rmVersion = rmd.getRMVersion();
}
}
if (!found) {
stopThreadForSequence(sequenceId, entry.isRmSource());
if (log.isDebugEnabled()) log.debug("Exit: Sender::internalRun, sequence has ended");
return false;
}
SenderBeanMgr mgr = storageManager.getSenderBeanMgr();
SenderBean senderBean = mgr.getNextMsgToSend(sequenceId);
if (senderBean == null) {
if (log.isDebugEnabled()) log.debug("Exit: Sender::internalRun, no message for this sequence");
return false; // Move on to the next sequence in the list
}
// work Id is used to define the piece of work that will be
// assigned to the Worker thread,
// to handle this Sender bean.
//workId contains a timeTiSend part to cater for retransmissions.
//This will cause retransmissions to be treated as new work.
String workId = senderBean.getMessageID() + senderBean.getTimeToSend();
// check weather the bean is already assigned to a worker.
if (getWorkerLock().isWorkPresent(workId)) {
// As there is already a worker running we are probably looping
// too fast, so sleep on the next loop.
if (log.isDebugEnabled()) {
String message = SandeshaMessageHelper.getMessage(
SandeshaMessageKeys.workAlreadyAssigned,
workId);
log.debug("Exit: Sender::internalRun, " + message + ", sleeping");
}
return true;
}
if(transaction != null) {
transaction.commit();
transaction = null;
}
// start a worker which will work on this messages.
SenderWorker worker = new SenderWorker(context, senderBean, rmVersion);
worker.setLock(getWorkerLock());
worker.setWorkId(workId);
threadPool.execute(worker);
// adding the workId to the lock after assigning it to a thread
// makes sure
// that all the workIds in the Lock are handled by threads.
getWorkerLock().addWork(workId);
// If we got to here then we found work to do on the sequence, so we should
// remember not to sleep at the end of the list of sequences.
processedMessage = true;
if(transaction != null && transaction.isActive()) transaction.commit();
transaction = null;
} catch (Exception e) {
// TODO : when this is the client side throw the exception to
// the client when necessary.
//TODO rollback only if a SandeshaStorageException.
//This allows the other Exceptions to be used within the Normal flow.
String message = SandeshaMessageHelper.getMessage(SandeshaMessageKeys.sendMsgError, e.toString());
log.debug(message, e);
} finally {
if (transaction != null && transaction.isActive()) {
try {
transaction.rollback();
transaction = null;
} catch (Exception e) {
String message = SandeshaMessageHelper
.getMessage(SandeshaMessageKeys.rollbackError, e.toString());
log.debug(message, e);