ソースを参照

Move POST processing to Broadcast.doPost method.

tags/Production_2016_10_17
ymlam 9年前
コミット
7daa802a25
1個のファイルの変更206行の追加4行の削除
  1. +206
    -4
      src/altk/comm/engine/Broadcast.java

+ 206
- 4
src/altk/comm/engine/Broadcast.java ファイルの表示

@@ -1,5 +1,6 @@
package altk.comm.engine;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
@@ -14,12 +15,15 @@ import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.apache.log4j.NDC;

import altk.comm.engine.exception.BroadcastError;
import altk.comm.engine.exception.BroadcastException;
import altk.comm.engine.exception.EngineException;
import altk.comm.engine.exception.PlatformError;
import altk.comm.engine.exception.PlatformException;
import altk.comm.engine.postback.PostBack;

/**
@@ -76,7 +80,7 @@ public abstract class Broadcast
protected static Logger myLogger = Logger.getLogger(Broadcast.class);

private Queue<Job> readyQueue;
private List<Thread> serviceThreadPool;
protected List<Service> serviceThreadPool;
private Object resumeFlag; // Semaphore for dispatcher threads to resume.
protected List<Recipient> recipientList;
//private int remainingJobs;
@@ -390,12 +394,145 @@ public abstract class Broadcast
this.jobReportRootNodeName = jobReportRootNodeName;
sleepBetweenJobs = SLEEP_BETWEEN_JOBS_DEFAULT;
readyQueue = new LinkedBlockingQueue<Job>();
serviceThreadPool = new ArrayList<Thread>();
serviceThreadPool = new ArrayList<Service>();
recipientList = new ArrayList<Recipient>();
scheduler = Executors.newScheduledThreadPool(SCHEDULER_THREAD_POOL_SIZE);
resumeFlag = new Object();
receiveTime = System.currentTimeMillis();
}
/**
* 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,
* and is much easier to read and comprehend.
* <p>It is responsible for
* <ul>
* <li>Replying with HTTP response, and closing HTTP request and response
* <li>Does broadcast and posts real-time progress, using post back queues
* from CommEngine.
* </ul>
* Strategy of execution:
* <ul>
* <li>Decode xml request
* <li>Set up Service threads
* <li> Invite derived class to set up contexts, one for each of the Service threads.
* <li>Do broadcast.
* </ul>
* This method is to be invoked by the CommEngine.doPost method, which fields a HTTP POST.
* <p>
* Adopting the use of this method by CommEngine
* is 100% compatible with derived classes VoiceBroadcast and EmailBroadcast
* existing today, 6/18/2016.
*
*
* @param request
* @param response
* @param commEngine
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response,
CommEngine commEngine)
{
myLogger.debug("Entering Broadcast.doPost method");
BroadcastException myException = null;
this.serviceThreadPoolSize = commEngine.getServiceThreadPoolSize();
try
{
boolean notInService = commEngine.notInService();
decode(request, notInService);
// Now that have decoded the id of this broadcast,
// ask CommEngine to install it with its id.
commEngine.installBroadcast(this);
if (notInService)
{
throw new PlatformException(PlatformError.RUNTIME_ERROR,
"Not in service");
}
if (recipientList.size() == 0)
{
// TODO: Got to return HTTP content before returning.
CommonLogger.activity.info("Broadcast " + getBroadcastId() + ": No recipients");
setState(BroadcastState.COMPLETED, "No recipients", null);
return;
}
postBack = (PostBack)commEngine.getPostBack(getPostBackURL(), broadcastType);
initSync(commEngine.getResources());
init(postBack);
if (getState() == BroadcastState.COMPLETED) return;
}
catch (BroadcastException e)
{
// TODO: Got to return HTTP content before returning.
myException = e;
setState(BroadcastState.ABORTED, e.errorCodeText, e.errorText);
CommonLogger.alarm.error("Broadcast aborted: " + e.getMessage());
myLogger.error("Broadcast aborted", e);
return;
}
catch (Throwable t)
{
// Caught stray unexpected runtime problem
CommonLogger.alarm.error("Broadcast aborted: " + t);
myLogger.error("Broadcast aborted", t);
myException = new BroadcastException(BroadcastError.PLATFORM_ERROR, t.getMessage());
setState(BroadcastState.ABORTED, myException.errorCodeText, myException.errorText);
}
finally
{
// Return regular or error response
String responseXML = getResponseXML(myException);
PrintWriter writer;
try
{
writer = response.getWriter();
writer.write(responseXML);
writer.close();
}
catch (IOException e)
{
myLogger.error("Failed to write reponse to requester. Aborts broadcast." );
if (state != BroadcastState.ABORTED)
{
setState(BroadcastState.ABORTED, "Failed to reply to requester", e.getMessage());
}
return;
}
if (myException != null) return;
}
// So far so good, we now go ahead with completing
// initialization.
try
{
initAsync();
effectiveJobCount = recipientList.size();
// Create service thread pool to dispatch jobs,
// at the same time, setting up a list of service thread names
// for use by derived class to set up contexts in which
// these threads run.
myLogger.debug("At creating service threads, serviceThreadPoolSize = " + serviceThreadPoolSize);
List<String> serviceThreadNames = new ArrayList<String>();
for (int i = 0; i < serviceThreadPoolSize; i++)
{
String threadName = broadcastId + "_service_thread_" + i;
Service serviceThread = new Service(threadName);
serviceThreadPool.add(serviceThread);
serviceThreadNames.add(threadName);
}
//initServiceThreadContexts(serviceThreadNames);

doBroadcast();
}
catch (BroadcastException e)
{
setState(BroadcastState.ABORTED, e.errorCodeText, e.errorText);
CommonLogger.alarm.error("Broadcast aborted: " + e.getMessage());
myLogger.error("Broadcast aborted", e);
}
}
protected abstract void returnPrerequisites(ServicePrerequisites prerequisites);
@@ -504,6 +641,11 @@ public abstract class Broadcast
return launchRecordId;
}

/**
*
* @param e
* @return HTTP response for normal case (when exception e is null), or with exception
*/
public String getResponseXML(BroadcastException e)
{
String tagName = broadcastType + "_response";
@@ -833,6 +975,45 @@ public abstract class Broadcast
}
}
/**
* For use by the new Broadcast.doPost method.
* It changes state to RUNNING and waits for all Service threads
* to terminate after starting them.
* @throws BroadcastException
*/
public void doBroadcast() throws BroadcastException
{
setState(BroadcastState.RUNNING);

// Start the dispatcher threads
for (Service thread : serviceThreadPool)
{
thread.start();
}
for (Service thread : serviceThreadPool)
{
try
{
thread.join();
}
catch (InterruptedException e)
{
myLogger.error("Caught exception while waiting for a Service thread to terminate:" + e);
}
}
close();
myLogger.info("Broadcast " + getId() + " terminated");
}
/**
* Derived may release resources here.
*/
protected void close()
{
// Do nothing in base class
}
public void startProcessing() throws BroadcastException
{
effectiveJobCount = recipientList.size();
@@ -846,15 +1027,36 @@ public abstract class Broadcast
serviceThreadPool.add(serviceThread);
}

initServiceThreadContexts();
setState(BroadcastState.RUNNING);

// Start the dispatcher threads
for (Thread thread : serviceThreadPool)
for (Service thread : serviceThreadPool)
{
thread.start();
}
}
/**
* Derived class may set up environment before starting Service threads.
* @param serviceThreadNames
*/
protected void initServiceThreadContexts()
{
// Do nothing in base class
}
/**
* Experimental - needed to go with the also experimental method exec.
* @param serviceThreadNames
*/
protected void initServiceThreadContexts(List<String> serviceThreadNames)
{
// Do nothing in base class
}
private boolean threadsShouldStop()
{
BroadcastState state = getState();


読み込み中…
キャンセル
保存