|
Modified: ofbiz/branches/20120329_portletWidget/framework/service/src/org/ofbiz/service/job/JobManager.java
URL: http://svn.apache.org/viewvc/ofbiz/branches/20120329_portletWidget/framework/service/src/org/ofbiz/service/job/JobManager.java?rev=1369382&r1=1369381&r2=1369382&view=diff ============================================================================== --- ofbiz/branches/20120329_portletWidget/framework/service/src/org/ofbiz/service/job/JobManager.java (original) +++ ofbiz/branches/20120329_portletWidget/framework/service/src/org/ofbiz/service/job/JobManager.java Sat Aug 4 18:11:00 2012 @@ -23,12 +23,13 @@ import java.sql.Timestamp; import java.util.Date; import java.util.List; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.RejectedExecutionException; import javolution.util.FastList; -import javolution.util.FastMap; +import org.ofbiz.base.util.Assert; import org.ofbiz.base.util.Debug; -import org.ofbiz.base.util.GeneralRuntimeException; import org.ofbiz.base.util.UtilDateTime; import org.ofbiz.base.util.UtilMisc; import org.ofbiz.base.util.UtilProperties; @@ -45,8 +46,8 @@ import org.ofbiz.entity.serialize.XmlSer import org.ofbiz.entity.transaction.GenericTransactionException; import org.ofbiz.entity.transaction.TransactionUtil; import org.ofbiz.service.DispatchContext; -import org.ofbiz.service.GenericDispatcher; import org.ofbiz.service.LocalDispatcher; +import org.ofbiz.service.ServiceContainer; import org.ofbiz.service.calendar.RecurrenceInfo; import org.ofbiz.service.calendar.RecurrenceInfoException; import org.ofbiz.service.config.ServiceConfigUtil; @@ -54,178 +55,201 @@ import org.ofbiz.service.config.ServiceC /** * JobManager */ -public class JobManager { +public final class JobManager { + public static final String module = JobManager.class.getName(); public static final String instanceId = UtilProperties.getPropertyValue("general.properties", "unique.instanceId", "ofbiz0"); public static final Map<String, Object> updateFields = UtilMisc.<String, Object>toMap("runByInstanceId", instanceId, "statusId", "SERVICE_QUEUED"); - public static final String module = JobManager.class.getName(); - public static Map<String, JobManager> registeredManagers = FastMap.newInstance(); + private static final ConcurrentHashMap<String, JobManager> registeredManagers = new ConcurrentHashMap<String, JobManager>(); + private static boolean isShutDown = false; - protected Delegator delegator; - protected JobPoller jp; + private static void assertIsRunning() { + if (isShutDown) { + throw new IllegalStateException("OFBiz shutting down"); + } + } - /** Creates a new JobManager object. */ - public JobManager(Delegator delegator) { - this(delegator, true); + public static JobManager getInstance(Delegator delegator, boolean enablePoller) { + assertIsRunning(); + Assert.notNull("delegator", delegator); + JobManager jm = JobManager.registeredManagers.get(delegator.getDelegatorName()); + if (jm == null) { + jm = new JobManager(delegator); + JobManager.registeredManagers.putIfAbsent(delegator.getDelegatorName(), jm); + jm = JobManager.registeredManagers.get(delegator.getDelegatorName()); + if (enablePoller) { + jm.enablePoller(); + } + } + return jm; } - public JobManager(Delegator delegator, boolean enabled) { - if (delegator == null) { - throw new GeneralRuntimeException("ERROR: null delegator passed, cannot create JobManager"); + /** gets the recurrence info object for a job. */ + public static RecurrenceInfo getRecurrenceInfo(GenericValue job) { + try { + if (job != null && !UtilValidate.isEmpty(job.getString("recurrenceInfoId"))) { + if (job.get("cancelDateTime") != null) { + // cancel has been flagged, no more recurrence + return null; + } + GenericValue ri = job.getRelatedOne("RecurrenceInfo", false); + if (ri != null) { + return new RecurrenceInfo(ri); + } else { + return null; + } + } else { + return null; + } + } catch (GenericEntityException e) { + Debug.logError(e, "Problem getting RecurrenceInfo entity from JobSandbox", module); + } catch (RecurrenceInfoException re) { + Debug.logError(re, "Problem creating RecurrenceInfo instance: " + re.getMessage(), module); } - if (JobManager.registeredManagers.get(delegator.getDelegatorName()) != null) { - throw new GeneralRuntimeException("JobManager for [" + delegator.getDelegatorName() + "] already running"); + return null; + } + + public static void shutDown() { + isShutDown = true; + for (JobManager jm : registeredManagers.values()) { + jm.shutdown(); } + } + private final Delegator delegator; + private final JobPoller jp; + private boolean pollerEnabled = false; + + private JobManager(Delegator delegator) { this.delegator = delegator; - jp = new JobPoller(this, enabled); - JobManager.registeredManagers.put(delegator.getDelegatorName(), this); + jp = new JobPoller(this); } - public static JobManager getInstance(Delegator delegator, boolean enabled) - { - JobManager jm = JobManager.registeredManagers.get(delegator.getDelegatorName()); - if (jm == null) { - jm = new JobManager(delegator, enabled); + private synchronized void enablePoller() { + if (!pollerEnabled) { + pollerEnabled = true; + reloadCrashedJobs(); + jp.enable(); } - return jm; } - /** Queues a Job to run now. */ - public void runJob(Job job) throws JobManagerException { - if (job.isValid()) { - jp.queueNow(job); - } + /** Returns the Delegator. */ + public Delegator getDelegator() { + return this.delegator; } - /** Returns the ServiceDispatcher. */ + /** Returns the LocalDispatcher. */ public LocalDispatcher getDispatcher() { - LocalDispatcher thisDispatcher = GenericDispatcher.getLocalDispatcher(delegator.getDelegatorName(), delegator); + LocalDispatcher thisDispatcher = ServiceContainer.getLocalDispatcher(delegator.getDelegatorName(), delegator); return thisDispatcher; } - /** Returns the Delegator. */ - public Delegator getDelegator() { - return this.delegator; + /** + * Get a List of each threads current state. + * + * @return List containing a Map of each thread's state. + */ + public Map<String, Object> getPoolState() { + return jp.getPoolState(); } public synchronized List<Job> poll() { + assertIsRunning(); List<Job> poll = FastList.newInstance(); - // sort the results by time List<String> order = UtilMisc.toList("runTime"); - // basic query - List<EntityExpr> expressions = UtilMisc.toList(EntityCondition.makeCondition("runTime", EntityOperator.LESS_THAN_EQUAL_TO, - UtilDateTime.nowTimestamp()), EntityCondition.makeCondition("startDateTime", EntityOperator.EQUALS, null), - EntityCondition.makeCondition("cancelDateTime", EntityOperator.EQUALS, null), - EntityCondition.makeCondition("runByInstanceId", EntityOperator.EQUALS, null)); - + List<EntityExpr> expressions = UtilMisc.toList(EntityCondition.makeCondition("runTime", EntityOperator.LESS_THAN_EQUAL_TO, UtilDateTime.nowTimestamp()), + EntityCondition.makeCondition("startDateTime", EntityOperator.EQUALS, null), EntityCondition.makeCondition("cancelDateTime", + EntityOperator.EQUALS, null), EntityCondition.makeCondition("runByInstanceId", EntityOperator.EQUALS, null)); // limit to just defined pools List<String> pools = ServiceConfigUtil.getRunPools(); List<EntityExpr> poolsExpr = UtilMisc.toList(EntityCondition.makeCondition("poolId", EntityOperator.EQUALS, null)); if (pools != null) { - for (String poolName: pools) { + for (String poolName : pools) { poolsExpr.add(EntityCondition.makeCondition("poolId", EntityOperator.EQUALS, poolName)); } } - // make the conditions EntityCondition baseCondition = EntityCondition.makeCondition(expressions); EntityCondition poolCondition = EntityCondition.makeCondition(poolsExpr, EntityOperator.OR); EntityCondition mainCondition = EntityCondition.makeCondition(UtilMisc.toList(baseCondition, poolCondition)); - // we will loop until we have no more to do boolean pollDone = false; - while (!pollDone) { - // an extra protection for synchronization, help make sure we don't get in here more than once - synchronized (this) { - boolean beganTransaction = false; - - try { - beganTransaction = TransactionUtil.begin(); - if (!beganTransaction) { - Debug.logError("Unable to poll for jobs; transaction was not started by this process", module); - return null; - } - - List<Job> localPoll = FastList.newInstance(); - - // first update the jobs w/ this instance running information - delegator.storeByCondition("JobSandbox", updateFields, mainCondition); - - // now query all the 'queued' jobs for this instance - List<GenericValue> jobEnt = delegator.findByAnd("JobSandbox", updateFields, order, false); - //jobEnt = delegator.findByCondition("JobSandbox", mainCondition, null, order); - - if (UtilValidate.isNotEmpty(jobEnt)) { - for (GenericValue v: jobEnt) { - DispatchContext dctx = getDispatcher().getDispatchContext(); - if (dctx == null) { - Debug.logError("Unable to locate DispatchContext object; not running job!", module); - continue; - } - Job job = new PersistedServiceJob(dctx, v, null); // TODO fix the requester - try { - job.queue(); - localPoll.add(job); - } catch (InvalidJobException e) { - Debug.logError(e, module); - } + boolean beganTransaction = false; + try { + beganTransaction = TransactionUtil.begin(); + if (!beganTransaction) { + Debug.logError("Unable to poll for jobs; transaction was not started by this process", module); + return null; + } + List<Job> localPoll = FastList.newInstance(); + // first update the jobs w/ this instance running information + delegator.storeByCondition("JobSandbox", updateFields, mainCondition); + // now query all the 'queued' jobs for this instance + List<GenericValue> jobEnt = delegator.findByAnd("JobSandbox", updateFields, order, false); + // jobEnt = delegator.findByCondition("JobSandbox", mainCondition, null, order); + if (UtilValidate.isNotEmpty(jobEnt)) { + for (GenericValue v : jobEnt) { + DispatchContext dctx = getDispatcher().getDispatchContext(); + if (dctx == null) { + Debug.logError("Unable to locate DispatchContext object; not running job!", module); + continue; + } + Job job = new PersistedServiceJob(dctx, v, null); // TODO fix the requester + try { + job.queue(); + localPoll.add(job); + } catch (InvalidJobException e) { + Debug.logError(e, module); } - } else { - pollDone = true; - } - - // nothing should go wrong at this point, so add to the general list - poll.addAll(localPoll); - } catch (Throwable t) { - // catch Throwable so nothing slips through the cracks... this is a fairly sensitive operation - String errMsg = "Error in polling JobSandbox: [" + t.toString() + "]. Rolling back transaction."; - Debug.logError(t, errMsg, module); - try { - // only rollback the transaction if we started one... - TransactionUtil.rollback(beganTransaction, errMsg, t); - } catch (GenericEntityException e2) { - Debug.logError(e2, "[Delegator] Could not rollback transaction: " + e2.toString(), module); - } - } finally { - try { - // only commit the transaction if we started one... but make sure we try - TransactionUtil.commit(beganTransaction); - } catch (GenericTransactionException e) { - String errMsg = "Transaction error trying to commit when polling and updating the JobSandbox: " + e.toString(); - // we don't really want to do anything different, so just log and move on - Debug.logError(e, errMsg, module); } + } else { + pollDone = true; + } + // nothing should go wrong at this point, so add to the general list + poll.addAll(localPoll); + } catch (Throwable t) { + // catch Throwable so nothing slips through the cracks... this is a fairly sensitive operation + String errMsg = "Error in polling JobSandbox: [" + t.toString() + "]. Rolling back transaction."; + Debug.logError(t, errMsg, module); + try { + // only rollback the transaction if we started one... + TransactionUtil.rollback(beganTransaction, errMsg, t); + } catch (GenericEntityException e2) { + Debug.logError(e2, "[Delegator] Could not rollback transaction: " + e2.toString(), module); + } + } finally { + try { + // only commit the transaction if we started one... but make sure we try + TransactionUtil.commit(beganTransaction); + } catch (GenericTransactionException e) { + String errMsg = "Transaction error trying to commit when polling and updating the JobSandbox: " + e.toString(); + // we don't really want to do anything different, so just log and move on + Debug.logError(e, errMsg, module); } } } return poll; } - public synchronized void reloadCrashedJobs() { - String instanceId = UtilProperties.getPropertyValue("general.properties", "unique.instanceId", "ofbiz0"); + private void reloadCrashedJobs() { List<GenericValue> crashed = null; - List<EntityExpr> exprs = UtilMisc.toList(EntityCondition.makeCondition("runByInstanceId", instanceId)); exprs.add(EntityCondition.makeCondition("statusId", EntityOperator.EQUALS, "SERVICE_RUNNING")); EntityConditionList<EntityExpr> ecl = EntityCondition.makeCondition(exprs); - try { crashed = delegator.findList("JobSandbox", ecl, null, UtilMisc.toList("startDateTime"), null, false); } catch (GenericEntityException e) { Debug.logError(e, "Unable to load crashed jobs", module); } - if (UtilValidate.isNotEmpty(crashed)) { try { int rescheduled = 0; - for (GenericValue job: crashed) { + for (GenericValue job : crashed) { Timestamp now = UtilDateTime.nowTimestamp(); - Debug.log("Scheduling Job : " + job, module); - + Debug.logInfo("Scheduling Job : " + job, module); String pJobId = job.getString("parentJobId"); if (pJobId == null) { pJobId = job.getString("jobId"); @@ -238,33 +262,49 @@ public class JobManager { newJob.set("startDateTime", null); newJob.set("runByInstanceId", null); delegator.createSetNextSeqId(newJob); - // set the cancel time on the old job to the same as the re-schedule time job.set("statusId", "SERVICE_CRASHED"); job.set("cancelDateTime", now); delegator.store(job); - rescheduled++; } - - if (Debug.infoOn()) Debug.logInfo("-- " + rescheduled + " jobs re-scheduled", module); + if (Debug.infoOn()) + Debug.logInfo("-- " + rescheduled + " jobs re-scheduled", module); } catch (GenericEntityException e) { Debug.logError(e, module); } - } else { - if (Debug.infoOn()) Debug.logInfo("No crashed jobs to re-schedule", module); + if (Debug.infoOn()) + Debug.logInfo("No crashed jobs to re-schedule", module); + } + } + + /** Queues a Job to run now. + * @throws IllegalStateException if the Job Manager is shut down. + * @throws RejectedExecutionException if the poller is stopped. + */ + public void runJob(Job job) throws JobManagerException { + assertIsRunning(); + if (job.isValid()) { + jp.queueNow(job); } } /** * Schedule a job to start at a specific time with specific recurrence info - *@param serviceName The name of the service to invoke - *@param context The context for the service - *@param startTime The time in milliseconds the service should run - *@param frequency The frequency of the recurrence (HOURLY,DAILY,MONTHLY,etc) - *@param interval The interval of the frequency recurrence - *@param count The number of times to repeat + * + * @param serviceName + * The name of the service to invoke + *@param context + * The context for the service + *@param startTime + * The time in milliseconds the service should run + *@param frequency + * The frequency of the recurrence (HOURLY,DAILY,MONTHLY,etc) + *@param interval + * The interval of the frequency recurrence + *@param count + * The number of times to repeat */ public void schedule(String serviceName, Map<String, ? extends Object> context, long startTime, int frequency, int interval, int count) throws JobManagerException { schedule(serviceName, context, startTime, frequency, interval, count, 0); @@ -272,65 +312,113 @@ public class JobManager { /** * Schedule a job to start at a specific time with specific recurrence info - *@param serviceName The name of the service to invoke - *@param context The context for the service - *@param startTime The time in milliseconds the service should run - *@param frequency The frequency of the recurrence (HOURLY,DAILY,MONTHLY,etc) - *@param interval The interval of the frequency recurrence - *@param endTime The time in milliseconds the service should expire + * + * @param serviceName + * The name of the service to invoke + *@param context + * The context for the service + *@param startTime + * The time in milliseconds the service should run + *@param frequency + * The frequency of the recurrence (HOURLY,DAILY,MONTHLY,etc) + *@param interval + * The interval of the frequency recurrence + *@param count + * The number of times to repeat + *@param endTime + * The time in milliseconds the service should expire */ - public void schedule(String serviceName, Map<String, ? extends Object> context, long startTime, int frequency, int interval, long endTime) throws JobManagerException { - schedule(serviceName, context, startTime, frequency, interval, -1, endTime); + public void schedule(String serviceName, Map<String, ? extends Object> context, long startTime, int frequency, int interval, int count, long endTime) throws JobManagerException { + schedule(null, serviceName, context, startTime, frequency, interval, count, endTime); } /** * Schedule a job to start at a specific time with specific recurrence info - *@param serviceName The name of the service to invoke - *@param context The context for the service - *@param startTime The time in milliseconds the service should run - *@param frequency The frequency of the recurrence (HOURLY,DAILY,MONTHLY,etc) - *@param interval The interval of the frequency recurrence - *@param count The number of times to repeat - *@param endTime The time in milliseconds the service should expire + * + * @param serviceName + * The name of the service to invoke + *@param context + * The context for the service + *@param startTime + * The time in milliseconds the service should run + *@param frequency + * The frequency of the recurrence (HOURLY,DAILY,MONTHLY,etc) + *@param interval + * The interval of the frequency recurrence + *@param endTime + * The time in milliseconds the service should expire */ - public void schedule(String serviceName, Map<String, ? extends Object> context, long startTime, int frequency, int interval, int count, long endTime) throws JobManagerException { - schedule(null, serviceName, context, startTime, frequency, interval, count, endTime); + public void schedule(String serviceName, Map<String, ? extends Object> context, long startTime, int frequency, int interval, long endTime) throws JobManagerException { + schedule(serviceName, context, startTime, frequency, interval, -1, endTime); } /** * Schedule a job to start at a specific time with specific recurrence info - *@param poolName The name of the pool to run the service from - *@param serviceName The name of the service to invoke - *@param context The context for the service - *@param startTime The time in milliseconds the service should run - *@param frequency The frequency of the recurrence (HOURLY,DAILY,MONTHLY,etc) - *@param interval The interval of the frequency recurrence - *@param count The number of times to repeat - *@param endTime The time in milliseconds the service should expire + * + * @param poolName + * The name of the pool to run the service from + *@param serviceName + * The name of the service to invoke + *@param context + * The context for the service + *@param startTime + * The time in milliseconds the service should run + *@param frequency + * The frequency of the recurrence (HOURLY,DAILY,MONTHLY,etc) + *@param interval + * The interval of the frequency recurrence + *@param count + * The number of times to repeat + *@param endTime + * The time in milliseconds the service should expire */ - public void schedule(String poolName, String serviceName, Map<String, ? extends Object> context, long startTime, int frequency, int interval, int count, long endTime) throws JobManagerException { + public void schedule(String poolName, String serviceName, Map<String, ? extends Object> context, long startTime, int frequency, + int interval, int count, long endTime) throws JobManagerException { schedule(null, null, serviceName, context, startTime, frequency, interval, count, endTime, -1); } /** * Schedule a job to start at a specific time with specific recurrence info - *@param jobName The name of the job - *@param poolName The name of the pool to run the service from - *@param serviceName The name of the service to invoke - *@param context The context for the service - *@param startTime The time in milliseconds the service should run - *@param frequency The frequency of the recurrence (HOURLY,DAILY,MONTHLY,etc) - *@param interval The interval of the frequency recurrence - *@param count The number of times to repeat - *@param endTime The time in milliseconds the service should expire - *@param maxRetry The max number of retries on failure (-1 for no max) + * + * @param poolName + * The name of the pool to run the service from + *@param serviceName + * The name of the service to invoke + *@param dataId + * The persisted context (RuntimeData.runtimeDataId) + *@param startTime + * The time in milliseconds the service should run */ - public void schedule(String jobName, String poolName, String serviceName, Map<String, ? extends Object> context, long startTime, int frequency, int interval, int count, long endTime, int maxRetry) throws JobManagerException { - if (delegator == null) { - Debug.logWarning("No delegator referenced; cannot schedule job.", module); - return; - } + public void schedule(String poolName, String serviceName, String dataId, long startTime) throws JobManagerException { + schedule(null, poolName, serviceName, dataId, startTime, -1, 0, 1, 0, -1); + } + /** + * Schedule a job to start at a specific time with specific recurrence info + * + * @param jobName + * The name of the job + *@param poolName + * The name of the pool to run the service from + *@param serviceName + * The name of the service to invoke + *@param context + * The context for the service + *@param startTime + * The time in milliseconds the service should run + *@param frequency + * The frequency of the recurrence (HOURLY,DAILY,MONTHLY,etc) + *@param interval + * The interval of the frequency recurrence + *@param count + * The number of times to repeat + *@param endTime + * The time in milliseconds the service should expire + *@param maxRetry + * The max number of retries on failure (-1 for no max) + */ + public void schedule(String jobName, String poolName, String serviceName, Map<String, ? extends Object> context, long startTime, + int frequency, int interval, int count, long endTime, int maxRetry) throws JobManagerException { // persist the context String dataId = null; try { @@ -345,41 +433,38 @@ public class JobManager { } catch (IOException ioe) { throw new JobManagerException(ioe.getMessage(), ioe); } - // schedule the job schedule(jobName, poolName, serviceName, dataId, startTime, frequency, interval, count, endTime, maxRetry); } /** * Schedule a job to start at a specific time with specific recurrence info - *@param poolName The name of the pool to run the service from - *@param serviceName The name of the service to invoke - *@param dataId The persisted context (RuntimeData.runtimeDataId) - *@param startTime The time in milliseconds the service should run - */ - public void schedule(String poolName, String serviceName, String dataId, long startTime) throws JobManagerException { - schedule(null, poolName, serviceName, dataId, startTime, -1, 0, 1, 0, -1); - } - - /** - * Schedule a job to start at a specific time with specific recurrence info - *@param jobName The name of the job - *@param poolName The name of the pool to run the service from - *@param serviceName The name of the service to invoke - *@param dataId The persisted context (RuntimeData.runtimeDataId) - *@param startTime The time in milliseconds the service should run - *@param frequency The frequency of the recurrence (HOURLY,DAILY,MONTHLY,etc) - *@param interval The interval of the frequency recurrence - *@param count The number of times to repeat - *@param endTime The time in milliseconds the service should expire - *@param maxRetry The max number of retries on failure (-1 for no max) + * + * @param jobName + * The name of the job + *@param poolName + * The name of the pool to run the service from + *@param serviceName + * The name of the service to invoke + *@param dataId + * The persisted context (RuntimeData.runtimeDataId) + *@param startTime + * The time in milliseconds the service should run + *@param frequency + * The frequency of the recurrence (HOURLY,DAILY,MONTHLY,etc) + *@param interval + * The interval of the frequency recurrence + *@param count + * The number of times to repeat + *@param endTime + * The time in milliseconds the service should expire + *@param maxRetry + * The max number of retries on failure (-1 for no max) + * @throws IllegalStateException if the Job Manager is shut down. */ - public void schedule(String jobName, String poolName, String serviceName, String dataId, long startTime, int frequency, int interval, int count, long endTime, int maxRetry) throws JobManagerException { - if (delegator == null) { - Debug.logWarning("No delegator referenced; cannot schedule job.", module); - return; - } - + public void schedule(String jobName, String poolName, String serviceName, String dataId, long startTime, int frequency, int interval, + int count, long endTime, int maxRetry) throws JobManagerException { + assertIsRunning(); // create the recurrence String infoId = null; if (frequency > -1 && count != 0) { @@ -390,28 +475,23 @@ public class JobManager { throw new JobManagerException(e.getMessage(), e); } } - // set the persisted fields if (UtilValidate.isEmpty(jobName)) { jobName = Long.toString((new Date().getTime())); } - Map<String, Object> jFields = UtilMisc.<String, Object>toMap("jobName", jobName, "runTime", new java.sql.Timestamp(startTime), + Map<String, Object> jFields = UtilMisc.<String, Object> toMap("jobName", jobName, "runTime", new java.sql.Timestamp(startTime), "serviceName", serviceName, "statusId", "SERVICE_PENDING", "recurrenceInfoId", infoId, "runtimeDataId", dataId); - // set the pool ID if (UtilValidate.isNotEmpty(poolName)) { jFields.put("poolId", poolName); } else { jFields.put("poolId", ServiceConfigUtil.getSendPool()); } - // set the loader name jFields.put("loaderName", delegator.getDelegatorName()); - // set the max retry jFields.put("maxRetry", Long.valueOf(maxRetry)); jFields.put("currentRetryCount", new Long(0)); - // create the value and store GenericValue jobV; try { @@ -422,63 +502,12 @@ public class JobManager { } } - /** - * Kill a JobInvoker Thread. - * @param threadName Name of the JobInvoker Thread to kill. - */ - public void killThread(String threadName) { - jp.killThread(threadName); - } - - /** - * Get a List of each threads current state. - * @return List containing a Map of each thread's state. - */ - public List<Map<String, Object>> processList() { - return jp.getPoolState(); - } - /** Close out the scheduler thread. */ public void shutdown() { - if (jp != null) { - jp.stop(); - jp = null; - Debug.logInfo("JobManager: Stopped Scheduler Thread.", module); - } - } - - @Override - public void finalize() throws Throwable { - this.shutdown(); - super.finalize(); - } - - /** gets the recurrence info object for a job. */ - public static RecurrenceInfo getRecurrenceInfo(GenericValue job) { - try { - if (job != null && !UtilValidate.isEmpty(job.getString("recurrenceInfoId"))) { - if (job.get("cancelDateTime") != null) { - // cancel has been flagged, no more recurrence - return null; - } - GenericValue ri = job.getRelatedOne("RecurrenceInfo", false); - - if (ri != null) { - return new RecurrenceInfo(ri); - } else { - return null; - } - } else { - return null; - } - } catch (GenericEntityException e) { - e.printStackTrace(); - Debug.logError(e, "Problem getting RecurrenceInfo entity from JobSandbox", module); - } catch (RecurrenceInfoException re) { - re.printStackTrace(); - Debug.logError(re, "Problem creating RecurrenceInfo instance: " + re.getMessage(), module); - } - return null; + Debug.logInfo("Stopping the JobManager...", module); + registeredManagers.remove(delegator.getDelegatorName(), this); + jp.stop(); + Debug.logInfo("JobManager stopped.", module); } } Modified: ofbiz/branches/20120329_portletWidget/framework/service/src/org/ofbiz/service/job/JobPoller.java URL: http://svn.apache.org/viewvc/ofbiz/branches/20120329_portletWidget/framework/service/src/org/ofbiz/service/job/JobPoller.java?rev=1369382&r1=1369381&r2=1369382&view=diff ============================================================================== --- ofbiz/branches/20120329_portletWidget/framework/service/src/org/ofbiz/service/job/JobPoller.java (original) +++ ofbiz/branches/20120329_portletWidget/framework/service/src/org/ofbiz/service/job/JobPoller.java Sat Aug 4 18:11:00 2012 @@ -18,93 +18,64 @@ *******************************************************************************/ package org.ofbiz.service.job; +import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Map; - -import javolution.util.FastList; -import javolution.util.FastMap; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.RejectedExecutionException; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; import org.ofbiz.base.util.Debug; import org.ofbiz.service.config.ServiceConfigUtil; +import org.apache.commons.lang.math.NumberUtils; + /** * JobPoller - Polls for persisted jobs to run. */ -public class JobPoller implements Runnable { +public final class JobPoller implements Runnable { public static final String module = JobPoller.class.getName(); - public static final int MIN_THREADS = 1; public static final int MAX_THREADS = 15; - public static final int MAX_JOBS = 3; public static final int POLL_WAIT = 20000; - //public static final long MAX_TTL = 18000000; + public static final long THREAD_TTL = 18000000; - protected Thread thread = null; - protected List<JobInvoker> pool = null; - protected List<Job> run = null; - protected JobManager jm = null; - - protected volatile boolean isRunning = false; + private final JobManager jm; + private final ThreadPoolExecutor executor; + private final String name; + private boolean enabled = false; /** * Creates a new JobScheduler - * @param jm JobManager associated with this scheduler + * + * @param jm + * JobManager associated with this scheduler */ - public JobPoller(JobManager jm, boolean enabled) { + public JobPoller(JobManager jm) { + this.name = jm.getDelegator().getDelegatorName(); this.jm = jm; - this.run = FastList.newInstance(); - - // create the thread pool - this.pool = createThreadPool(); - - if (enabled) { - // re-load crashed jobs - this.jm.reloadCrashedJobs(); + this.executor = new ThreadPoolExecutor(minThreads(), maxThreads(), getTTL(), TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(), + new JobInvokerThreadFactory(this.name), new ThreadPoolExecutor.AbortPolicy()); + } + public synchronized void enable() { + if (!enabled) { + enabled = true; // start the thread only if polling is enabled if (pollEnabled()) { - // create the poller thread - thread = new Thread(this, this.toString()); + Thread thread = new Thread(this, "OFBiz-JobPoller-" + this.name); thread.setDaemon(false); - // start the poller - this.isRunning = true; thread.start(); } } } - protected JobPoller() {} - - public synchronized void run() { - try { - // wait 30 seconds before the first poll - java.lang.Thread.sleep(30000); - } catch (InterruptedException e) { - } - while (isRunning) { - try { - // grab a list of jobs to run. - List<Job> pollList = jm.poll(); - //Debug.logInfo("Received poll list from JobManager [" + pollList.size() + "]", module); - - for (Job job : pollList) { - if (job.isValid()) { - queueNow(job); - //Debug.logInfo("Job [" + job.getJobId() + "] is queued", module); - } - } - // NOTE: using sleep instead of wait for stricter locking - java.lang.Thread.sleep(pollWaitTime()); - } catch (InterruptedException e) { - Debug.logError(e, module); - stop(); - } - } - } - /** * Returns the JobManager */ @@ -112,139 +83,47 @@ public class JobPoller implements Runnab return jm; } - /** - * Stops the JobPoller - */ - public void stop() { - isRunning = false; - destroyThreadPool(); - } - - public List<Map<String, Object>> getPoolState() { - List<Map<String, Object>> stateList = FastList.newInstance(); - for (JobInvoker invoker: this.pool) { - Map<String, Object> stateMap = FastMap.newInstance(); - stateMap.put("threadName", invoker.getName()); - stateMap.put("threadId", invoker.getThreadId()); - stateMap.put("jobName", invoker.getJobName()); - stateMap.put("serviceName", invoker.getServiceName()); - stateMap.put("usage", invoker.getUsage()); - stateMap.put("ttl", invoker.getTimeRemaining()); - stateMap.put("runTime", invoker.getCurrentRuntime()); - stateMap.put("status", invoker.getCurrentStatus()); - stateList.add(stateMap); - } - return stateList; - } - - /** - * Stops all threads in the threadPool and clears - * the pool as final step. - */ - private void destroyThreadPool() { - Debug.logInfo("Destroying thread pool...", module); - for (JobInvoker ji: pool) { - ji.stop(); - } - pool.clear(); - } - - public synchronized void killThread(String threadName) { - JobInvoker inv = findThread(threadName); - if (inv != null) { - inv.kill(); - this.pool.remove(inv); - } - } - - private JobInvoker findThread(String threadName) { - for (JobInvoker inv: pool) { - if (threadName.equals(inv.getName())) { - return inv; - } + public Map<String, Object> getPoolState() { + Map<String, Object> poolState = new HashMap<String, Object>(); + poolState.put("pollerName", this.name); + poolState.put("pollerThreadName", "OFBiz-JobPoller-" + this.name); + poolState.put("invokerThreadNameFormat", "OFBiz-JobInvoker-" + this.name + "-<SEQ>"); + poolState.put("keepAliveTimeInSeconds", this.executor.getKeepAliveTime(TimeUnit.SECONDS)); + poolState.put("numberOfCoreInvokerThreads", this.executor.getCorePoolSize()); + poolState.put("currentNumberOfInvokerThreads", this.executor.getPoolSize()); + poolState.put("numberOfActiveInvokerThreads", this.executor.getActiveCount()); + poolState.put("maxNumberOfInvokerThreads", this.executor.getMaximumPoolSize()); + poolState.put("greatestNumberOfInvokerThreads", this.executor.getLargestPoolSize()); + poolState.put("numberOfCompletedTasks", this.executor.getCompletedTaskCount()); + BlockingQueue<Runnable> queue = this.executor.getQueue(); + List<Map<String, Object>> taskList = new ArrayList<Map<String, Object>>(); + Map<String, Object> taskInfo = null; + for (Runnable task : queue) { + JobInvoker jobInvoker = (JobInvoker) task; + taskInfo = new HashMap<String, Object>(); + taskInfo.put("id", jobInvoker.getJobId()); + taskInfo.put("name", jobInvoker.getJobName()); + taskInfo.put("serviceName", jobInvoker.getServiceName()); + taskInfo.put("time", jobInvoker.getTime()); + taskInfo.put("runtime", jobInvoker.getCurrentRuntime()); + taskList.add(taskInfo); } - return null; + poolState.put("taskList", taskList); + return poolState; } - /** - * Returns the next job to run - */ - public Job next() { - if (run.size() > 0) { - // NOTE: this syncrhonized isn't really necessary as the only method that calls it is already synchronized (the JobInvoker.run method), so this is here as an added protection especially for the case where it might be used differently in the future - synchronized (run) { - // make sure the size is still greater than zero - if (run.size() > 0) { - return run.remove(0); - } - } - } - return null; - } - - /** - * Adds a job to the RUN queue - */ - public void queueNow(Job job) { - //Debug.logInfo("[" + Thread.currentThread().getId() + "] Begin queueNow; holds run lock? " + Thread.holdsLock(run), module); - - // NOTE DEJ20071201 MUST use a different object for the lock here because the "this" object is always held by the poller thread in the run method above (which sleeps and runs) - synchronized (run) { - run.add(job); - } - if (Debug.verboseOn()) Debug.logVerbose("New run queue size: " + run.size(), module); - if (run.size() > pool.size() && pool.size() < maxThreads()) { - synchronized (pool) { - if (run.size() > pool.size() && pool.size() < maxThreads()) { - int calcSize = (run.size() / jobsPerThread()) - (pool.size()); - int addSize = calcSize > maxThreads() ? maxThreads() : calcSize; - - for (int i = 0; i < addSize; i++) { - JobInvoker iv = new JobInvoker(this, invokerWaitTime()); - pool.add(iv); - } - } - } - } - } - - /** - * Removes a thread from the pool. - * @param invoker The invoker to remove. - */ - public void removeThread(JobInvoker invoker) { - if (pool != null) { - synchronized (pool) { - pool.remove(invoker); - invoker.stop(); - } - } - - if (pool != null && pool.size() < minThreads()) { - synchronized (pool) { - for (int i = 0; i < minThreads() - pool.size(); i++) { - JobInvoker iv = new JobInvoker(this, invokerWaitTime()); - pool.add(iv); - } - } - } - } - - // Creates the invoker pool - private List<JobInvoker> createThreadPool() { - List<JobInvoker> threadPool = FastList.newInstance(); - - while (threadPool.size() < minThreads()) { - JobInvoker iv = new JobInvoker(this, invokerWaitTime()); - threadPool.add(iv); + private long getTTL() { + long ttl = THREAD_TTL; + try { + ttl = NumberUtils.toLong(ServiceConfigUtil.getElementAttr("thread-pool", "ttl")); + } catch (NumberFormatException nfe) { + Debug.logError("Problems reading value from attribute [ttl] of element [thread-pool] in serviceengine.xml file [" + nfe.toString() + "]. Using default (" + THREAD_TTL + ").", module); } - - return threadPool; + return ttl; } private int maxThreads() { int max = MAX_THREADS; - try { max = Integer.parseInt(ServiceConfigUtil.getElementAttr("thread-pool", "max-threads")); } catch (NumberFormatException nfe) { @@ -255,7 +134,6 @@ public class JobPoller implements Runnab private int minThreads() { int min = MIN_THREADS; - try { min = Integer.parseInt(ServiceConfigUtil.getElementAttr("thread-pool", "min-threads")); } catch (NumberFormatException nfe) { @@ -264,31 +142,15 @@ public class JobPoller implements Runnab return min; } - private int jobsPerThread() { - int jobs = MAX_JOBS; - - try { - jobs = Integer.parseInt(ServiceConfigUtil.getElementAttr("thread-pool", "jobs")); - } catch (NumberFormatException nfe) { - Debug.logError("Problems reading values from serviceengine.xml file [" + nfe.toString() + "]. Using defaults.", module); - } - return jobs; - } - - private int invokerWaitTime() { - int wait = JobInvoker.WAIT_TIME; - - try { - wait = Integer.parseInt(ServiceConfigUtil.getElementAttr("thread-pool", "wait-millis")); - } catch (NumberFormatException nfe) { - Debug.logError("Problems reading values from serviceengine.xml file [" + nfe.toString() + "]. Using defaults.", module); - } - return wait; + private boolean pollEnabled() { + String enabled = ServiceConfigUtil.getElementAttr("thread-pool", "poll-enabled"); + if (enabled.equalsIgnoreCase("false")) + return false; + return true; } private int pollWaitTime() { int poll = POLL_WAIT; - try { poll = Integer.parseInt(ServiceConfigUtil.getElementAttr("thread-pool", "poll-db-millis")); } catch (NumberFormatException nfe) { @@ -297,19 +159,64 @@ public class JobPoller implements Runnab return poll; } - private boolean pollEnabled() { - String enabled = ServiceConfigUtil.getElementAttr("thread-pool", "poll-enabled"); - - if (enabled.equalsIgnoreCase("false")) - return false; + /** + * Adds a job to the RUN queue. + * @throws RejectedExecutionException if the poller is stopped. + */ + public void queueNow(Job job) { + this.executor.execute(new JobInvoker(job)); + } - // also make sure we have a delegator to use for polling - if (jm.getDelegator() == null) { - Debug.logWarning("No delegator referenced; not starting job poller.", module); - return false; + public synchronized void run() { + try { + // wait 30 seconds before the first poll + java.lang.Thread.sleep(30000); + } catch (InterruptedException e) { + } + while (!executor.isShutdown()) { + try { + // grab a list of jobs to run. + List<Job> pollList = jm.poll(); + // Debug.logInfo("Received poll list from JobManager [" + pollList.size() + "]", module); + for (Job job : pollList) { + if (job.isValid()) { + queueNow(job); + // Debug.logInfo("Job [" + job.getJobId() + "] is queued", module); + } + } + // NOTE: using sleep instead of wait for stricter locking + java.lang.Thread.sleep(pollWaitTime()); + } catch (InterruptedException e) { + Debug.logError(e, module); + stop(); + } } + Debug.logInfo("JobPoller " + this.name + " thread terminated.", module); + } - return true; + /** + * Stops the JobPoller + */ + void stop() { + Debug.logInfo("Shutting down thread pool for JobPoller " + this.name, module); + this.executor.shutdown(); + try { + // Wait 60 seconds for existing tasks to terminate + if (!this.executor.awaitTermination(60, TimeUnit.SECONDS)) { + // abrupt shutdown (cancel currently executing tasks) + Debug.logInfo("Attempting abrupt shut down of thread pool for JobPoller " + this.name, module); + this.executor.shutdownNow(); + // Wait 60 seconds for tasks to respond to being cancelled + if (!this.executor.awaitTermination(60, TimeUnit.SECONDS)) { + Debug.logWarning("Unable to shutdown the thread pool for JobPoller " + this.name, module); + } + } + } catch (InterruptedException ie) { + // re cancel if current thread was also interrupted + this.executor.shutdownNow(); + // preserve interrupt status + Thread.currentThread().interrupt(); + } + Debug.logInfo("Shutdown completed of thread pool for JobPoller " + this.name, module); } } - Modified: ofbiz/branches/20120329_portletWidget/framework/service/src/org/ofbiz/service/mail/JavaMailContainer.java URL: http://svn.apache.org/viewvc/ofbiz/branches/20120329_portletWidget/framework/service/src/org/ofbiz/service/mail/JavaMailContainer.java?rev=1369382&r1=1369381&r2=1369382&view=diff ============================================================================== --- ofbiz/branches/20120329_portletWidget/framework/service/src/org/ofbiz/service/mail/JavaMailContainer.java (original) +++ ofbiz/branches/20120329_portletWidget/framework/service/src/org/ofbiz/service/mail/JavaMailContainer.java Sat Aug 4 18:11:00 2012 @@ -22,8 +22,9 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Properties; -import java.util.Timer; -import java.util.TimerTask; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; import javax.mail.FetchProfile; import javax.mail.Flags; import javax.mail.Folder; @@ -48,9 +49,9 @@ import org.ofbiz.entity.Delegator; import org.ofbiz.entity.DelegatorFactory; import org.ofbiz.entity.GenericValue; import org.ofbiz.entity.GenericEntityException; -import org.ofbiz.service.GenericDispatcher; import org.ofbiz.service.LocalDispatcher; import org.ofbiz.service.GenericServiceException; +import org.ofbiz.service.ServiceContainer; public class JavaMailContainer implements Container { @@ -62,7 +63,7 @@ public class JavaMailContainer implement protected GenericValue userLogin = null; protected long timerDelay = 300000; protected long maxSize = 1000000; - protected Timer pollTimer = null; + protected ScheduledExecutorService pollTimer = null; protected boolean deleteMail = false; // whether to delete emails after fetching them. protected String configFile = null; @@ -80,7 +81,7 @@ public class JavaMailContainer implement this.name = name; this.configFile = configFile; this.stores = new LinkedHashMap<Store, Session>(); - this.pollTimer = new Timer(); + this.pollTimer = Executors.newScheduledThreadPool(1); } /** @@ -97,7 +98,7 @@ public class JavaMailContainer implement this.deleteMail = "true".equals(ContainerConfig.getPropertyValue(cfg, "delete-mail", "false")); this.delegator = DelegatorFactory.getDelegator(delegatorName); - this.dispatcher = GenericDispatcher.getLocalDispatcher(dispatcherName, delegator); + this.dispatcher = ServiceContainer.getLocalDispatcher(dispatcherName, delegator); this.timerDelay = ContainerConfig.getPropertyValue(cfg, "poll-delay", 300000); this.maxSize = ContainerConfig.getPropertyValue(cfg, "maxSize", 1000000); // maximum size in bytes @@ -126,7 +127,7 @@ public class JavaMailContainer implement // start the polling timer if (UtilValidate.isNotEmpty(stores)) { - pollTimer.schedule(new PollerTask(dispatcher, userLogin), timerDelay, timerDelay); + pollTimer.scheduleAtFixedRate(new PollerTask(dispatcher, userLogin), timerDelay, timerDelay, TimeUnit.MILLISECONDS); } else { Debug.logWarning("No JavaMail Store(s) configured; poller disabled.", module); } @@ -142,7 +143,7 @@ public class JavaMailContainer implement */ public void stop() throws ContainerException { // stop the poller - this.pollTimer.cancel(); + this.pollTimer.shutdown(); Debug.logWarning("stop JavaMail poller", module); } @@ -250,7 +251,7 @@ public class JavaMailContainer implement } } - class PollerTask extends TimerTask { + class PollerTask implements Runnable { LocalDispatcher dispatcher; GenericValue userLogin; @@ -260,7 +261,6 @@ public class JavaMailContainer implement this.userLogin = userLogin; } - @Override public void run() { if (UtilValidate.isNotEmpty(stores)) { for (Map.Entry<Store, Session> entry: stores.entrySet()) { Modified: ofbiz/branches/20120329_portletWidget/framework/service/src/org/ofbiz/service/rmi/RmiServiceContainer.java URL: http://svn.apache.org/viewvc/ofbiz/branches/20120329_portletWidget/framework/service/src/org/ofbiz/service/rmi/RmiServiceContainer.java?rev=1369382&r1=1369381&r2=1369382&view=diff ============================================================================== --- ofbiz/branches/20120329_portletWidget/framework/service/src/org/ofbiz/service/rmi/RmiServiceContainer.java (original) +++ ofbiz/branches/20120329_portletWidget/framework/service/src/org/ofbiz/service/rmi/RmiServiceContainer.java Sat Aug 4 18:11:00 2012 @@ -32,8 +32,8 @@ import org.ofbiz.base.container.Containe import org.ofbiz.base.util.UtilValidate; import org.ofbiz.entity.Delegator; import org.ofbiz.entity.DelegatorFactory; -import org.ofbiz.service.GenericDispatcher; import org.ofbiz.service.LocalDispatcher; +import org.ofbiz.service.ServiceContainer; /** * RMI Service Engine Container / Dispatcher @@ -49,7 +49,7 @@ public class RmiServiceContainer impleme // Container methods /** - * @see org.ofbiz.base.container.Container#init(java.lang.String[], java.lang.String) + * @see org.ofbiz.base.container.Container#init(String[] args, String name, String configFile) */ public void init(String[] args, String name, String configFile) { this.containerName = name; @@ -126,7 +126,7 @@ public class RmiServiceContainer impleme Delegator delegator = DelegatorFactory.getDelegator(delegatorProp.value); // create the LocalDispatcher - LocalDispatcher dispatcher = GenericDispatcher.getLocalDispatcher(name, delegator); + LocalDispatcher dispatcher = ServiceContainer.getLocalDispatcher(name, delegator); // create the RemoteDispatcher try { Modified: ofbiz/branches/20120329_portletWidget/framework/start/src/org/ofbiz/base/start/Config.java URL: http://svn.apache.org/viewvc/ofbiz/branches/20120329_portletWidget/framework/start/src/org/ofbiz/base/start/Config.java?rev=1369382&r1=1369381&r2=1369382&view=diff ============================================================================== --- ofbiz/branches/20120329_portletWidget/framework/start/src/org/ofbiz/base/start/Config.java (original) +++ ofbiz/branches/20120329_portletWidget/framework/start/src/org/ofbiz/base/start/Config.java Sat Aug 4 18:11:00 2012 @@ -25,8 +25,10 @@ import java.io.IOException; import java.io.InputStream; import java.net.InetAddress; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Locale; +import java.util.Map; import java.util.Properties; import java.util.TimeZone; @@ -71,7 +73,7 @@ public class Config { public String containerConfig; public String instrumenterClassName; public String instrumenterFile; - public List<String> loaders; + public List<Map> loaders; public String logDir; public String ofbizHome; public boolean requireCommJar = false; @@ -209,8 +211,6 @@ public class Config { fis = new FileInputStream(propsFile); if (fis != null) { props.load(fis); - } else { - throw new FileNotFoundException(); } } catch (FileNotFoundException e2) { // do nothing; we will see empty props below @@ -420,14 +420,18 @@ public class Config { instrumenterFile = getProp(props, "ofbiz.instrumenterFile", null); // loader classes - loaders = new ArrayList<String>(); + loaders = new ArrayList<Map>(); int currentPosition = 1; + Map<String, String> loader = null; while (true) { + loader = new HashMap<String, String>(); String loaderClass = props.getProperty("ofbiz.start.loader" + currentPosition); if (loaderClass == null || loaderClass.length() == 0) { break; } else { - loaders.add(loaderClass); + loader.put("class", loaderClass); + loader.put("profiles", props.getProperty("ofbiz.start.loader" + currentPosition + ".loaders")); + loaders.add(loader); currentPosition++; } } Modified: ofbiz/branches/20120329_portletWidget/framework/start/src/org/ofbiz/base/start/InstrumenterWorker.java URL: http://svn.apache.org/viewvc/ofbiz/branches/20120329_portletWidget/framework/start/src/org/ofbiz/base/start/InstrumenterWorker.java?rev=1369382&r1=1369381&r2=1369382&view=diff ============================================================================== --- ofbiz/branches/20120329_portletWidget/framework/start/src/org/ofbiz/base/start/InstrumenterWorker.java (original) +++ ofbiz/branches/20120329_portletWidget/framework/start/src/org/ofbiz/base/start/InstrumenterWorker.java Sat Aug 4 18:11:00 2012 @@ -26,7 +26,7 @@ import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; -import java.lang.management.ManagementFactory; +import java.lang.Runtime; import java.net.URL; import java.net.URLClassLoader; import java.util.List; @@ -73,7 +73,7 @@ public final class InstrumenterWorker { } catch (ClassNotFoundException e) { return srcPaths; } - ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(ManagementFactory.getOperatingSystemMXBean().getAvailableProcessors()); + ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(Runtime.getRuntime().availableProcessors()); try { File instrumenterFile = new File(instrumenterFileName); instrumenterFile.delete(); Modified: ofbiz/branches/20120329_portletWidget/framework/start/src/org/ofbiz/base/start/Start.java URL: http://svn.apache.org/viewvc/ofbiz/branches/20120329_portletWidget/framework/start/src/org/ofbiz/base/start/Start.java?rev=1369382&r1=1369381&r2=1369382&view=diff ============================================================================== --- ofbiz/branches/20120329_portletWidget/framework/start/src/org/ofbiz/base/start/Start.java (original) +++ ofbiz/branches/20120329_portletWidget/framework/start/src/org/ofbiz/base/start/Start.java Sat Aug 4 18:11:00 2012 @@ -31,6 +31,7 @@ import java.net.Socket; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Map; import java.util.concurrent.atomic.AtomicReference; /** @@ -253,11 +254,12 @@ public class Start { ClassLoader classloader = Thread.currentThread().getContextClassLoader(); synchronized (this.loaders) { // initialize the loaders - for (String loaderClassName: config.loaders) { + for (Map loaderMap: config.loaders) { if (this.serverState.get() == ServerState.STOPPING) { return; } try { + String loaderClassName = (String)loaderMap.get("class"); Class<?> loaderClass = classloader.loadClass(loaderClassName); StartupLoader loader = (StartupLoader) loaderClass.newInstance(); loader.load(config, loaderArgs.toArray(new String[loaderArgs.size()])); @@ -398,7 +400,7 @@ public class Start { private ServerSocket serverSocket = null; AdminPortThread() throws StartupException { - super("AdminPortThread"); + super("OFBiz-AdminPortThread"); try { this.serverSocket = new ServerSocket(config.adminPort, 1, config.adminAddress); } catch (IOException e) { Modified: ofbiz/branches/20120329_portletWidget/framework/start/src/org/ofbiz/base/start/both.properties URL: http://svn.apache.org/viewvc/ofbiz/branches/20120329_portletWidget/framework/start/src/org/ofbiz/base/start/both.properties?rev=1369382&r1=1369381&r2=1369382&view=diff ============================================================================== --- ofbiz/branches/20120329_portletWidget/framework/start/src/org/ofbiz/base/start/both.properties (original) +++ ofbiz/branches/20120329_portletWidget/framework/start/src/org/ofbiz/base/start/both.properties Sat Aug 4 18:11:00 2012 @@ -46,6 +46,7 @@ ofbiz.start.loader1=org.ofbiz.base.splas # --- StartupLoader implementations to load (in order) ofbiz.start.loader2=org.ofbiz.base.container.ContainerLoader +ofbiz.start.loader2.loaders=main,pos,rmi # -- Splash Logo ofbiz.start.splash.logo=framework/images/webapp/images/ofbiz_logo.gif Modified: ofbiz/branches/20120329_portletWidget/framework/start/src/org/ofbiz/base/start/install.properties URL: http://svn.apache.org/viewvc/ofbiz/branches/20120329_portletWidget/framework/start/src/org/ofbiz/base/start/install.properties?rev=1369382&r1=1369381&r2=1369382&view=diff ============================================================================== --- ofbiz/branches/20120329_portletWidget/framework/start/src/org/ofbiz/base/start/install.properties (original) +++ ofbiz/branches/20120329_portletWidget/framework/start/src/org/ofbiz/base/start/install.properties Sat Aug 4 18:11:00 2012 @@ -39,10 +39,11 @@ #ofbiz.log.dir=runtime/logs # --- Location (relative to ofbiz.home) for (normal) container configuration -ofbiz.container.config=framework/base/config/install-containers.xml +#ofbiz.container.config=framework/base/config/ofbiz-containers.xml # --- StartupLoader implementations to load (in order) ofbiz.start.loader1=org.ofbiz.base.container.ContainerLoader +ofbiz.start.loader1.loaders=install # -- Enable the shutdown hook #ofbiz.enable.hook=false Modified: ofbiz/branches/20120329_portletWidget/framework/start/src/org/ofbiz/base/start/jetty.properties URL: http://svn.apache.org/viewvc/ofbiz/branches/20120329_portletWidget/framework/start/src/org/ofbiz/base/start/jetty.properties?rev=1369382&r1=1369381&r2=1369382&view=diff ============================================================================== --- ofbiz/branches/20120329_portletWidget/framework/start/src/org/ofbiz/base/start/jetty.properties (original) +++ ofbiz/branches/20120329_portletWidget/framework/start/src/org/ofbiz/base/start/jetty.properties Sat Aug 4 18:11:00 2012 @@ -52,6 +52,7 @@ ofbiz.admin.key=so3du5kasd5dn # --- StartupLoader implementations to load (in order) ofbiz.start.loader1=org.ofbiz.base.container.ContainerLoader +ofbiz.start.loader1.loaders=main,rmi # -- Enable the shutdown hook ofbiz.enable.hook=true Modified: ofbiz/branches/20120329_portletWidget/framework/start/src/org/ofbiz/base/start/pos.properties URL: http://svn.apache.org/viewvc/ofbiz/branches/20120329_portletWidget/framework/start/src/org/ofbiz/base/start/pos.properties?rev=1369382&r1=1369381&r2=1369382&view=diff ============================================================================== --- ofbiz/branches/20120329_portletWidget/framework/start/src/org/ofbiz/base/start/pos.properties (original) +++ ofbiz/branches/20120329_portletWidget/framework/start/src/org/ofbiz/base/start/pos.properties Sat Aug 4 18:11:00 2012 @@ -39,13 +39,14 @@ #ofbiz.log.dir=runtime/logs # --- Location (relative to ofbiz.home) for (normal) container configuration -ofbiz.container.config=framework/base/config/pos-containers.xml +#ofbiz.container.config=framework/base/config/ofbiz-containers.xml # -- StartupLoader implementation for Splash Screen ofbiz.start.loader1=org.ofbiz.base.splash.SplashLoader # --- StartupLoader implementations to load (in order) ofbiz.start.loader2=org.ofbiz.base.container.ContainerLoader +ofbiz.start.loader2.loaders=pos # -- Splash Logo ofbiz.start.splash.logo=framework/images/webapp/images/ofbiz_logo.gif Modified: ofbiz/branches/20120329_portletWidget/framework/start/src/org/ofbiz/base/start/rmi.properties URL: http://svn.apache.org/viewvc/ofbiz/branches/20120329_portletWidget/framework/start/src/org/ofbiz/base/start/rmi.properties?rev=1369382&r1=1369381&r2=1369382&view=diff ============================================================================== --- ofbiz/branches/20120329_portletWidget/framework/start/src/org/ofbiz/base/start/rmi.properties (original) +++ ofbiz/branches/20120329_portletWidget/framework/start/src/org/ofbiz/base/start/rmi.properties Sat Aug 4 18:11:00 2012 @@ -39,10 +39,11 @@ #ofbiz.log.dir=runtime/logs # --- Location (relative to ofbiz.home) for (normal) container configuration -ofbiz.container.config=framework/base/config/rmi-containers.xml +#ofbiz.container.config=framework/base/config/ofbiz-containers.xml # --- StartupLoader implementations to load (in order) ofbiz.start.loader1=org.ofbiz.base.container.ContainerLoader +ofbiz.start.loader1.loaders=rmi # -- Enable the shutdown hook #ofbiz.enable.hook=true Modified: ofbiz/branches/20120329_portletWidget/framework/start/src/org/ofbiz/base/start/start.properties URL: http://svn.apache.org/viewvc/ofbiz/branches/20120329_portletWidget/framework/start/src/org/ofbiz/base/start/start.properties?rev=1369382&r1=1369381&r2=1369382&view=diff ============================================================================== --- ofbiz/branches/20120329_portletWidget/framework/start/src/org/ofbiz/base/start/start.properties (original) +++ ofbiz/branches/20120329_portletWidget/framework/start/src/org/ofbiz/base/start/start.properties Sat Aug 4 18:11:00 2012 @@ -52,6 +52,7 @@ ofbiz.admin.key=so3du5kasd5dn # --- StartupLoader implementations to load (in order) ofbiz.start.loader1=org.ofbiz.base.container.ContainerLoader +ofbiz.start.loader1.loaders=main,rmi # -- Enable the shutdown hook #ofbiz.enable.hook=true Modified: ofbiz/branches/20120329_portletWidget/framework/start/src/org/ofbiz/base/start/test.properties URL: http://svn.apache.org/viewvc/ofbiz/branches/20120329_portletWidget/framework/start/src/org/ofbiz/base/start/test.properties?rev=1369382&r1=1369381&r2=1369382&view=diff ============================================================================== --- ofbiz/branches/20120329_portletWidget/framework/start/src/org/ofbiz/base/start/test.properties (original) +++ ofbiz/branches/20120329_portletWidget/framework/start/src/org/ofbiz/base/start/test.properties Sat Aug 4 18:11:00 2012 @@ -39,10 +39,11 @@ #ofbiz.log.dir=runtime/logs # --- Location (relative to ofbiz.home) for (normal) container configuration -ofbiz.container.config=framework/base/config/test-containers.xml +#ofbiz.container.config=framework/base/config/ofbiz-containers.xml # --- StartupLoader implementations to load (in order) ofbiz.start.loader1=org.ofbiz.base.container.ContainerLoader +ofbiz.start.loader1.loaders=test,rmi # -- Enable the shutdown hook #ofbiz.enable.hook=true Modified: ofbiz/branches/20120329_portletWidget/framework/start/src/org/ofbiz/base/start/testlist.properties URL: http://svn.apache.org/viewvc/ofbiz/branches/20120329_portletWidget/framework/start/src/org/ofbiz/base/start/testlist.properties?rev=1369382&r1=1369381&r2=1369382&view=diff ============================================================================== --- ofbiz/branches/20120329_portletWidget/framework/start/src/org/ofbiz/base/start/testlist.properties (original) +++ ofbiz/branches/20120329_portletWidget/framework/start/src/org/ofbiz/base/start/testlist.properties Sat Aug 4 18:11:00 2012 @@ -39,10 +39,11 @@ #ofbiz.log.dir=runtime/logs # --- Location (relative to ofbiz.home) for (normal) container configuration -ofbiz.container.config=framework/base/config/testlist-containers.xml +#ofbiz.container.config=framework/base/config/ofbiz-containers.xml # --- StartupLoader implementations to load (in order) ofbiz.start.loader1=org.ofbiz.base.container.ContainerLoader +ofbiz.start.loader1.loaders=testlist # -- Enable the shutdown hook #ofbiz.enable.hook=true Modified: ofbiz/branches/20120329_portletWidget/framework/testtools/ofbiz-component.xml URL: http://svn.apache.org/viewvc/ofbiz/branches/20120329_portletWidget/framework/testtools/ofbiz-component.xml?rev=1369382&r1=1369381&r2=1369382&view=diff ============================================================================== --- ofbiz/branches/20120329_portletWidget/framework/testtools/ofbiz-component.xml (original) +++ ofbiz/branches/20120329_portletWidget/framework/testtools/ofbiz-component.xml Sat Aug 4 18:11:00 2012 @@ -35,4 +35,6 @@ <service-resource type="model" loader="main" location="servicedef/services.xml"/> <container name="testtools-container" loaders="test" class="org.ofbiz.testtools.TestRunContainer"/> + <container name="testtools-container" loaders="testlist" class="org.ofbiz.testtools.TestListContainer"/> + </ofbiz-component> \ No newline at end of file Modified: ofbiz/branches/20120329_portletWidget/framework/testtools/src/org/ofbiz/testtools/ModelTestSuite.java URL: http://svn.apache.org/viewvc/ofbiz/branches/20120329_portletWidget/framework/testtools/src/org/ofbiz/testtools/ModelTestSuite.java?rev=1369382&r1=1369381&r2=1369382&view=diff ============================================================================== --- ofbiz/branches/20120329_portletWidget/framework/testtools/src/org/ofbiz/testtools/ModelTestSuite.java (original) +++ ofbiz/branches/20120329_portletWidget/framework/testtools/src/org/ofbiz/testtools/ModelTestSuite.java Sat Aug 4 18:11:00 2012 @@ -38,8 +38,8 @@ import org.ofbiz.entity.DelegatorFactory import org.ofbiz.entity.testtools.EntityTestCase; import org.ofbiz.minilang.MiniLangException; import org.ofbiz.minilang.SimpleMethod; -import org.ofbiz.service.GenericDispatcher; import org.ofbiz.service.LocalDispatcher; +import org.ofbiz.service.ServiceContainer; import org.ofbiz.service.testtools.OFBizTestCase; import org.w3c.dom.Element; @@ -71,7 +71,7 @@ public class ModelTestSuite { String uniqueSuffix = "-" + RandomStringUtils.randomAlphanumeric(10); this.delegator = DelegatorFactory.getDelegator(this.originalDelegatorName).makeTestDelegator(this.originalDelegatorName + uniqueSuffix); - this.dispatcher = GenericDispatcher.getLocalDispatcher(originalDispatcherName + uniqueSuffix, delegator); + this.dispatcher = ServiceContainer.getLocalDispatcher(originalDispatcherName + uniqueSuffix, delegator); for (Element testCaseElement : UtilXml.childElementList(mainElement, UtilMisc.toSet("test-case", "test-group"))) { String caseName = testCaseElement.getAttribute("case-name"); Modified: ofbiz/branches/20120329_portletWidget/framework/testtools/src/org/ofbiz/testtools/TestListContainer.java URL: http://svn.apache.org/viewvc/ofbiz/branches/20120329_portletWidget/framework/testtools/src/org/ofbiz/testtools/TestListContainer.java?rev=1369382&r1=1369381&r2=1369382&view=diff ============================================================================== --- ofbiz/branches/20120329_portletWidget/framework/testtools/src/org/ofbiz/testtools/TestListContainer.java (original) +++ ofbiz/branches/20120329_portletWidget/framework/testtools/src/org/ofbiz/testtools/TestListContainer.java Sat Aug 4 18:11:00 2012 @@ -59,7 +59,7 @@ public class TestListContainer implement } /** - * @see org.ofbiz.base.container.Container#init(java.lang.String[], java.lang.String) + * @see org.ofbiz.base.container.Container#init(String[] args, String name, String configFile) */ public void init(String[] args, String name, String configFile) { this.name = name; Modified: ofbiz/branches/20120329_portletWidget/framework/testtools/src/org/ofbiz/testtools/TestRunContainer.java URL: http://svn.apache.org/viewvc/ofbiz/branches/20120329_portletWidget/framework/testtools/src/org/ofbiz/testtools/TestRunContainer.java?rev=1369382&r1=1369381&r2=1369382&view=diff ============================================================================== --- ofbiz/branches/20120329_portletWidget/framework/testtools/src/org/ofbiz/testtools/TestRunContainer.java (original) +++ ofbiz/branches/20120329_portletWidget/framework/testtools/src/org/ofbiz/testtools/TestRunContainer.java Sat Aug 4 18:11:00 2012 @@ -60,7 +60,7 @@ public class TestRunContainer implements private String name; /** - * @see org.ofbiz.base.container.Container#init(java.lang.String[], java.lang.String) + * @see org.ofbiz.base.container.Container#init(String[] args, String name, String configFile) */ public void init(String[] args, String name, String configFile) { this.name = name; Modified: ofbiz/branches/20120329_portletWidget/framework/webapp/dtd/site-conf.xsd URL: http://svn.apache.org/viewvc/ofbiz/branches/20120329_portletWidget/framework/webapp/dtd/site-conf.xsd?rev=1369382&r1=1369381&r2=1369382&view=diff ============================================================================== --- ofbiz/branches/20120329_portletWidget/framework/webapp/dtd/site-conf.xsd (original) +++ ofbiz/branches/20120329_portletWidget/framework/webapp/dtd/site-conf.xsd Sat Aug 4 18:11:00 2012 @@ -189,6 +189,7 @@ under the License. <xs:sequence> <xs:element minOccurs="0" ref="description"/> <xs:element minOccurs="0" ref="security"/> + <xs:element minOccurs="0" ref="metric"/> <xs:element minOccurs="0" ref="event"/> <xs:element maxOccurs="unbounded" ref="response"/> </xs:sequence> @@ -325,7 +326,7 @@ under the License. <xs:attribute name="direct-request" default="true"> <xs:annotation> <xs:documentation> - If false the request can only be accessed in a chained request + If false the request can only be accessed in a chained request, default to true. </xs:documentation> </xs:annotation> <xs:simpleType> @@ -336,6 +337,60 @@ under the License. </xs:simpleType> </xs:attribute> </xs:attributeGroup> + <xs:element name="metric"> + <xs:annotation> + <xs:documentation> + Calculate and maintain an average response time for this request. Request metrics can be used + for monitoring and reporting. Metrics can also be used to trigger an alternate + response if the optional threshold attribute is used. + <br/><br/> + The metric works by gathering statistics until a configurable maximum is reached (number of + requests or elapsed time), then the average is calculated. A smoothing factor is used to + smooth differences between calculations. + </xs:documentation> + </xs:annotation> + <xs:complexType> + <xs:attribute name="name" type="xs:string" use="required"> + <xs:annotation> + <xs:documentation> + Each metric must have a unique name. + </xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute name="estimation-size" type="xs:string"> + <xs:annotation> + <xs:documentation> + Positive integer number of requests to include in the metrics calculation. Defaults to "100". + </xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute name="estimation-time" type="xs:string"> + <xs:annotation> + <xs:documentation> + Positive integer number of milliseconds to include in the metrics calculation. Defaults to "1000". + </xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute name="smoothing" type="xs:string"> + <xs:annotation> + <xs:documentation> + Positive decimal smoothing factor - used to smooth the differences between calculations. A value of "1" disables smoothing. Defaults to "0.7". + </xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute name="threshold" type="xs:string"> + <xs:annotation> + <xs:documentation> + The metric threshold in milliseconds. If the average response time exceeds this setting, + then a "threshold-exceeded" response code will be generated. That response code can be used + in a response element. The threshold check will ignore the first three requests - to give + the metric a chance to stablize after startup. A value of "0.0" disables the threshold. + Defaults to "0.0". + </xs:documentation> + </xs:annotation> + </xs:attribute> + </xs:complexType> + </xs:element> <xs:element name="event"> <xs:annotation> <xs:documentation> @@ -652,8 +707,7 @@ under the License. <xs:attribute type="xs:string" name="type" default="default"> <xs:annotation> <xs:documentation> - There are as much as types (of type view) as available defined and accessible event handlers. - Most used is screen, others are notably screenxml, screentext, screencsv, screenfop, ftl, http and birt + The name of the view handler that will render the output: screen, screenfop, ftl etc... A most comprehensive list can be found in the common-controller. </xs:documentation> </xs:annotation> Modified: ofbiz/branches/20120329_portletWidget/framework/webapp/src/org/ofbiz/webapp/control/ConfigXMLReader.java URL: http://svn.apache.org/viewvc/ofbiz/branches/20120329_portletWidget/framework/webapp/src/org/ofbiz/webapp/control/ConfigXMLReader.java?rev=1369382&r1=1369381&r2=1369382&view=diff ============================================================================== --- ofbiz/branches/20120329_portletWidget/framework/webapp/src/org/ofbiz/webapp/control/ConfigXMLReader.java (original) +++ ofbiz/branches/20120329_portletWidget/framework/webapp/src/org/ofbiz/webapp/control/ConfigXMLReader.java Sat Aug 4 18:11:00 2012 @@ -33,6 +33,8 @@ import javolution.util.FastMap; import javolution.util.FastSet; import org.ofbiz.base.location.FlexibleLocation; +import org.ofbiz.base.metrics.Metrics; +import org.ofbiz.base.metrics.MetricsFactory; import org.ofbiz.base.util.Debug; import org.ofbiz.base.util.FileUtil; import org.ofbiz.base.util.GeneralException; @@ -523,6 +525,7 @@ public class ConfigXMLReader { public boolean securityDirectRequest = true; public Map<String, RequestResponse> requestResponseMap = FastMap.newInstance(); + public Metrics metrics = null; public RequestMap(Element requestMapElement) { @@ -556,6 +559,11 @@ public class ConfigXMLReader { RequestResponse response = new RequestResponse(responseElement); requestResponseMap.put(response.name, response); } + // Get metrics. + Element metricsElement = UtilXml.firstChildElement(requestMapElement, "metric"); + if (metricsElement != null) { + this.metrics = MetricsFactory.getInstance(metricsElement); + } } } |
| Free forum by Nabble | Edit this page |
