|
|
|
@@ -74,12 +74,16 @@ public abstract class Broadcast |
|
|
|
private ScheduledExecutorService scheduler; |
|
|
|
private int serviceThreadPoolSize_default; |
|
|
|
private int jobsTotal; |
|
|
|
private int scheduledJobs; |
|
|
|
|
|
|
|
protected int transactions; |
|
|
|
protected int completedTransactions; |
|
|
|
|
|
|
|
public static enum BroadcastState |
|
|
|
{ |
|
|
|
ACCEPTED, |
|
|
|
RUNNING, |
|
|
|
ALLDONE, |
|
|
|
// ALLDONE, |
|
|
|
PAUSING, |
|
|
|
PAUSED, |
|
|
|
CANCELING, |
|
|
|
@@ -175,14 +179,15 @@ public abstract class Broadcast |
|
|
|
|
|
|
|
// Transitions from RUNNING |
|
|
|
toStates.put(BroadcastState.RUNNING, Arrays.asList( |
|
|
|
BroadcastState.COMPLETED, // after completed all sends |
|
|
|
BroadcastState.CANCELING, // User action |
|
|
|
BroadcastState.CANCELED, // User action |
|
|
|
BroadcastState.PAUSING, // User action |
|
|
|
BroadcastState.PAUSED, // User action |
|
|
|
BroadcastState.PURGED, // User action |
|
|
|
BroadcastState.ABORTED, // Service provider irrecoverable error |
|
|
|
BroadcastState.EXPIRED, |
|
|
|
BroadcastState.ALLDONE // Natural transition, if all ongoing calls complete and no more jobs in Dispatcher queues. |
|
|
|
BroadcastState.EXPIRED |
|
|
|
// BroadcastState.ALLDONE // Natural transition, if all ongoing calls complete and no more jobs in Dispatcher queues. |
|
|
|
)); |
|
|
|
|
|
|
|
// Transitions from CANCELING |
|
|
|
@@ -207,9 +212,9 @@ public abstract class Broadcast |
|
|
|
BroadcastState.PURGED // User action |
|
|
|
)); |
|
|
|
// Transitions from ALLDONE |
|
|
|
toStates.put(BroadcastState.ALLDONE, Arrays.asList( |
|
|
|
BroadcastState.COMPLETED // Natural transition, if all ongoing jobs complete and no more jobs in post queue |
|
|
|
)); |
|
|
|
//toStates.put(BroadcastState.ALLDONE, Arrays.asList( |
|
|
|
// BroadcastState.COMPLETED // Natural transition, if all ongoing jobs complete and no more jobs in post queue |
|
|
|
// )); |
|
|
|
} |
|
|
|
|
|
|
|
public static class StateChangeResult |
|
|
|
@@ -242,7 +247,7 @@ public abstract class Broadcast |
|
|
|
myLogger.info("Thread starting..."); |
|
|
|
for (;;) |
|
|
|
{ |
|
|
|
if (threadsShouldStop()) |
|
|
|
if (serviceThreadsShouldStop()) |
|
|
|
{ |
|
|
|
closeServiceProvider(serviceProviderPeer); |
|
|
|
myLogger.info("Thread terminating"); |
|
|
|
@@ -301,7 +306,7 @@ public abstract class Broadcast |
|
|
|
*/ |
|
|
|
prerequisites = secureServicePrerequisites(); |
|
|
|
|
|
|
|
if (threadsShouldStop() || threadsShouldPause()) |
|
|
|
if (serviceThreadsShouldStop() || threadsShouldPause()) |
|
|
|
{ |
|
|
|
returnPrerequisites(prerequisites); |
|
|
|
continue; |
|
|
|
@@ -347,6 +352,7 @@ public abstract class Broadcast |
|
|
|
// Service the jobs |
|
|
|
try |
|
|
|
{ |
|
|
|
incrementTransactions(batch.size()); |
|
|
|
processJobs(batch, serviceProviderPeer, prerequisites); |
|
|
|
} |
|
|
|
catch (EngineException e) |
|
|
|
@@ -399,7 +405,22 @@ public abstract class Broadcast |
|
|
|
|
|
|
|
receiveTime = System.currentTimeMillis(); |
|
|
|
} |
|
|
|
/** |
|
|
|
|
|
|
|
public int pendingJobs() |
|
|
|
{ |
|
|
|
return readyQueue.size() + scheduledJobs; |
|
|
|
} |
|
|
|
|
|
|
|
public void incrementTransactions(int size) { |
|
|
|
transactions += size; |
|
|
|
} |
|
|
|
|
|
|
|
public void incrementCompletedTransactions(int size) |
|
|
|
{ |
|
|
|
completedTransactions += size; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Experimental formulation where it takes over directing |
|
|
|
* the activity of a Broadcast, as it should, instead of relegating |
|
|
|
* it to CommEngine. This is directly invoked by CommEngine.doPost method, |
|
|
|
@@ -843,7 +864,7 @@ public abstract class Broadcast |
|
|
|
} |
|
|
|
} |
|
|
|
statusBf.append("<job_summary completed='" + getCompletedJobCount() + |
|
|
|
"' ready='" + getReadyJobCount() + "'"); |
|
|
|
"' ready='" + getPendingJobCount() + "'"); |
|
|
|
statusBf.append(" active='" + getActiveJobCount() + "'"); |
|
|
|
statusBf.append("></job_summary></" + topLevelTag + ">\r\n"); |
|
|
|
String statusReport = statusBf.toString(); |
|
|
|
@@ -1001,16 +1022,25 @@ public abstract class Broadcast |
|
|
|
myLogger.error("Caught exception while waiting for a Service thread to terminate:" + e); |
|
|
|
} |
|
|
|
} |
|
|
|
close(); |
|
|
|
setState(BroadcastState.COMPLETED); |
|
|
|
destroyResources(); |
|
|
|
postback.wrapup(); |
|
|
|
postback = null; |
|
|
|
myLogger.info("Broadcast " + getId() + " terminated"); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Derived class destroy resources needed for providing service |
|
|
|
*/ |
|
|
|
protected void destroyResources() {} |
|
|
|
|
|
|
|
/** |
|
|
|
* Derived may release resources here. |
|
|
|
*/ |
|
|
|
protected void close() |
|
|
|
{ |
|
|
|
postback.shutdownWhenDone(); |
|
|
|
myLogger.debug("In close()");; |
|
|
|
postback.wrapup(); |
|
|
|
postback = null; |
|
|
|
} |
|
|
|
|
|
|
|
@@ -1033,10 +1063,11 @@ public abstract class Broadcast |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private boolean threadsShouldStop() |
|
|
|
private boolean serviceThreadsShouldStop() |
|
|
|
{ |
|
|
|
return state == BroadcastState.CANCELING || |
|
|
|
state == BroadcastState.CANCELED || state.isFinal; |
|
|
|
state == BroadcastState.CANCELED || state.isFinal |
|
|
|
|| pendingJobs() == 0; |
|
|
|
} |
|
|
|
|
|
|
|
private boolean threadsShouldPause() |
|
|
|
@@ -1104,7 +1135,7 @@ public abstract class Broadcast |
|
|
|
// No more rescheduling on cancel, expire, or pause |
|
|
|
completedJobCount++; |
|
|
|
logJobCount("Completed a job"); |
|
|
|
if (allDone() && state==BroadcastState.RUNNING) setState(BroadcastState.ALLDONE); |
|
|
|
//if (allDone() && state==BroadcastState.RUNNING) setState(BroadcastState.ALLDONE); |
|
|
|
} |
|
|
|
else if (rescheduleTimeMS == 0) |
|
|
|
{ |
|
|
|
@@ -1118,18 +1149,18 @@ public abstract class Broadcast |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Logs effectiveJobCount, completedJobCount, readyQueue.size(), |
|
|
|
* Logs completedJobCount, readyQueue.size(), |
|
|
|
* active job count, and total. |
|
|
|
* Job statistics are collected by length of readyQueue, completedJobCount, |
|
|
|
* and effectiveJobCount. |
|
|
|
*/ |
|
|
|
private void logJobCount(String title) |
|
|
|
{ |
|
|
|
myLogger.debug(String.format("%s: completed: %d, active: %d, ready: %d, total jobs: %d, remaining %d", |
|
|
|
myLogger.debug(String.format("%s: completed: %d, active: %d, ready: %d, scheduled %d, total jobs: %d, remaining %d", |
|
|
|
title, |
|
|
|
completedJobCount, |
|
|
|
getActiveJobCount(), |
|
|
|
readyQueue.size(), |
|
|
|
scheduledJobs, |
|
|
|
jobsTotal, |
|
|
|
getRemainingJobCount() |
|
|
|
)); |
|
|
|
@@ -1137,17 +1168,17 @@ public abstract class Broadcast |
|
|
|
|
|
|
|
/** |
|
|
|
* Number of jobs to be completed. |
|
|
|
* Computed from effectiveJobCount and completedJobCount |
|
|
|
* @return |
|
|
|
*/ |
|
|
|
private int getRemainingJobCount() |
|
|
|
{ |
|
|
|
return jobsTotal - completedJobCount; |
|
|
|
return readyQueue.size() + scheduledJobs; |
|
|
|
} |
|
|
|
|
|
|
|
public ScheduledFuture<?> rescheduleJob(final Job job, long rescheduleTimeMS) |
|
|
|
{ |
|
|
|
Runnable r = new Runnable() { public void run() { addJob(job);}}; |
|
|
|
scheduledJobs++; |
|
|
|
Runnable r = new Runnable() { public void run() { scheduledJobs--; addJob(job);}}; |
|
|
|
return scheduler.schedule(r, rescheduleTimeMS, TimeUnit.MILLISECONDS); |
|
|
|
} |
|
|
|
|
|
|
|
@@ -1156,14 +1187,14 @@ public abstract class Broadcast |
|
|
|
return state; |
|
|
|
} |
|
|
|
|
|
|
|
public int getReadyJobCount() |
|
|
|
public int getPendingJobCount() |
|
|
|
{ |
|
|
|
switch (state) |
|
|
|
{ |
|
|
|
case RUNNING: |
|
|
|
case PAUSING: |
|
|
|
case PAUSED: |
|
|
|
return readyQueue.size(); |
|
|
|
return pendingJobs(); |
|
|
|
default: |
|
|
|
return 0; |
|
|
|
|
|
|
|
@@ -1182,4 +1213,15 @@ public abstract class Broadcast |
|
|
|
public boolean allDone() { |
|
|
|
return (completedJobCount == jobsTotal); |
|
|
|
} |
|
|
|
/* |
|
|
|
public boolean stopOnEmptyPostQueue() |
|
|
|
{ |
|
|
|
if (state == state.ALLDONE) return true; |
|
|
|
// Add the ALLDONE message to postQueue |
|
|
|
|
|
|
|
setState(BroadcastState.ALLDONE); |
|
|
|
// Do not stop as one report has just been added by the previous setState(). |
|
|
|
return false; |
|
|
|
} |
|
|
|
*/ |
|
|
|
} |