001: /*
002: * <copyright>
003: *
004: * Copyright 1997-2004 BBNT Solutions, LLC
005: * under sponsorship of the Defense Advanced Research Projects
006: * Agency (DARPA).
007: *
008: * You can redistribute this software and/or modify it under the
009: * terms of the Cougaar Open Source License as published on the
010: * Cougaar Open Source Website (www.cougaar.org).
011: *
012: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
013: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
014: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
015: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
016: * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
017: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
018: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
019: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
020: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
021: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
022: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
023: *
024: * </copyright>
025: */
026:
027: package org.cougaar.planning.plugin.deletion;
028:
029: import java.text.DateFormat;
030: import java.text.SimpleDateFormat;
031: import java.util.Collection;
032: import java.util.Date;
033: import java.util.Enumeration;
034: import java.util.Iterator;
035: import java.util.Random;
036: import java.util.Vector;
037:
038: import org.cougaar.core.agent.service.alarm.Alarm;
039: import org.cougaar.core.blackboard.IncrementalSubscription;
040: import org.cougaar.core.logging.LoggingServiceWithPrefix;
041: import org.cougaar.core.service.LoggingService;
042: import org.cougaar.planning.ldm.asset.Asset;
043: import org.cougaar.planning.ldm.asset.Entity;
044: import org.cougaar.planning.ldm.plan.Aggregation;
045: import org.cougaar.planning.ldm.plan.Allocation;
046: import org.cougaar.planning.ldm.plan.AllocationResult;
047: import org.cougaar.planning.ldm.plan.AspectType;
048: import org.cougaar.planning.ldm.plan.AspectValue;
049: import org.cougaar.planning.ldm.plan.Constraint;
050: import org.cougaar.planning.ldm.plan.Disposition;
051: import org.cougaar.planning.ldm.plan.Expansion;
052: import org.cougaar.planning.ldm.plan.NewComposition;
053: import org.cougaar.planning.ldm.plan.NewConstraint;
054: import org.cougaar.planning.ldm.plan.NewMPTask;
055: import org.cougaar.planning.ldm.plan.NewPrepositionalPhrase;
056: import org.cougaar.planning.ldm.plan.NewTask;
057: import org.cougaar.planning.ldm.plan.NewWorkflow;
058: import org.cougaar.planning.ldm.plan.Preference;
059: import org.cougaar.planning.ldm.plan.PrepositionalPhrase;
060: import org.cougaar.planning.ldm.plan.Relationship;
061: import org.cougaar.planning.ldm.plan.Role;
062: import org.cougaar.planning.ldm.plan.ScoringFunction;
063: import org.cougaar.planning.ldm.plan.Task;
064: import org.cougaar.planning.ldm.plan.Verb;
065: import org.cougaar.planning.plugin.legacy.SimplePlugin;
066: import org.cougaar.planning.plugin.util.PluginHelper;
067: import org.cougaar.util.UnaryPredicate;
068:
069: /**
070: * This plugin constructs a logplan consisting of tasks and their
071: * dispositions that can be deleted. It does the following:
072: * Inserts root tasks from time to time having timed activity.
073: * Expands root tasks into sequences of subtasks having time
074: * constraints.
075: * Aggregates subtasks of the same time within a time window.
076: * Allocates aggregated tasks to local or remote assets using a simple
077: * scheduling algorithm
078: * Watches for deletion of expired tasks and modifies its scheduling
079: * data to account for the deleted tasks
080: * Root tasks have no OfType preposition.
081: * Expansion of root tasks yields subtasks having OfType phrase
082: * Aggregation of subtasks produce tasks at the next level. These
083: * tasks have no OfType if they are to be allocated to another agent
084: **/
085: public class TestDeletionPlugin extends SimplePlugin {
086: /** Subscriptions to tasks **/
087:
088: private IncrementalSubscription tasksToExpand;
089: private IncrementalSubscription tasksToAggregate;
090: private IncrementalSubscription tasksToAllocateLocally;
091: private IncrementalSubscription tasksToAllocateRemotely;
092: private Vector[] mpTasks;
093: private IncrementalSubscription selfOrgs;
094:
095: /** Something to allocate subtasks to. **/
096: private Asset theRootAsset; // DO of root tasks
097: private Asset theExpAsset; // DO of expansion subtasks
098: private Asset theAggAsset; // DO of aggregation mptasks
099: private Asset theAllocAsset; // subject of allocations
100:
101: /** The Role we use for allocations **/
102: private Role testProviderRole;
103:
104: private Entity selfOrg;
105:
106: private Entity provider;
107:
108: /**
109: * The verbs that we use. Tasks to be expanded are
110: * TestDeletionExpand and Tasks to be aggregated are
111: * TestDeletionAggregate.
112: **/
113:
114: private static Verb testDeletionExpand = Verb
115: .get("TestDeletionExpand");
116: private static Verb testDeletionAggregate = Verb
117: .get("TestDeletionAggregate");
118:
119: /** The preposition used to specify task level **/
120: private static final String LEVEL = "AtLevel";
121:
122: /** The preposition used to specify subtask type **/
123: private static final String SUBTYPE = "Type";
124:
125: private static final int N_SUBTYPES = 3;
126: private static final int TYPE_ROOT = 1; // The subtype that is forwarded to another agent
127:
128: /** The preposition used to specify task duration **/
129: private static final String DURATION = "OfDuration";
130:
131: private static final long ONE_DAY = 86400000L;
132: private static final long ONE_HOUR = 3600000L;
133:
134: private long minRootTaskDelay = 30 * ONE_DAY;
135: private long maxRootTaskDelay = 60 * ONE_DAY;
136: private long minRootTaskDuration = 3 * ONE_DAY;
137: private long maxRootTaskDuration = 14 * ONE_DAY;
138: private long minInterTaskInterval = 1 * ONE_HOUR;
139: private long maxInterTaskInterval = 24 * ONE_HOUR;
140: private long AGGREGATION_PERIOD = 5 * ONE_DAY;
141: private long testDuration = 120 * ONE_DAY; // Run test for 120 days
142: private int nRoots = 0;
143: private int rootCount = 0; // Number of roots so far
144: private int level = 0; // Our level
145: private double clockRate = Double.NaN;
146: private Alarm newRootTimer;
147: private long testEnd;
148: private boolean useProvider = false;
149: private Random random = new Random();
150: private LoggingService logger;
151:
152: private UnaryPredicate expandPredicate = new UnaryPredicate() {
153: public boolean execute(Object o) {
154: if (o instanceof Task) {
155: Task task = (Task) o;
156: return (task.getVerb().equals(testDeletionExpand) && getLevel(task) == level);
157: }
158: return false;
159: }
160: };
161:
162: private UnaryPredicate aggregatePredicate = new UnaryPredicate() {
163: public boolean execute(Object o) {
164: if (o instanceof Task) {
165: Task task = (Task) o;
166: return (task.getVerb().equals(testDeletionAggregate) && getLevel(task) == level);
167: }
168: return false;
169: }
170: };
171:
172: private UnaryPredicate allocateLocallyPredicate = new UnaryPredicate() {
173: public boolean execute(Object o) {
174: if (o instanceof Task) {
175: Task task = (Task) o;
176: if (task.getVerb().equals(testDeletionExpand)
177: && getLevel(task) == level + 1) {
178: return !useProvider
179: || getSubtype(task) != TYPE_ROOT;
180: }
181: }
182: return false;
183: }
184: };
185:
186: private UnaryPredicate allocateRemotelyPredicate = new UnaryPredicate() {
187: public boolean execute(Object o) {
188: if (o instanceof Task) {
189: Task task = (Task) o;
190: if (task.getVerb().equals(testDeletionExpand)
191: && getLevel(task) == level + 1) {
192: return useProvider && getSubtype(task) == TYPE_ROOT;
193: }
194: }
195: return false;
196: }
197: };
198:
199: public void setLoggingService(LoggingService ls) {
200: logger = ls;
201: }
202:
203: public void load() {
204: super .load();
205: if (!(logger instanceof LoggingServiceWithPrefix)) {
206: logger = LoggingServiceWithPrefix.add(logger,
207: getMessageAddress().toString() + ": ");
208: }
209: }
210:
211: public void setupSubscriptions() {
212: Vector params = getParameters();
213: switch (params.size()) {
214: default:
215: case 5:
216: clockRate = Double
217: .parseDouble((String) params.elementAt(4));
218: case 4:
219: testDuration = parseInterval((String) params.elementAt(3));
220: case 3:
221: nRoots = Integer.parseInt((String) params.elementAt(2));
222: case 2:
223: useProvider = ((String) params.elementAt(1)).trim()
224: .toLowerCase().equals("true");
225: case 1:
226: level = Integer.parseInt((String) params.elementAt(0));
227: case 0:
228: break;
229: }
230: logger.info(" level=" + level);
231: logger.info(" useProvider=" + useProvider);
232: logger.info(" nRoots=" + nRoots);
233: logger.info("testDuration=" + testDuration);
234: logger.info(" clockRate=" + clockRate);
235: testProviderRole = Role.getRole("TestDeletionProvider");
236: theRootAsset = theLDMF.createInstance(theLDMF.createPrototype(
237: Asset.class, "TestRoot"));
238: theExpAsset = theLDMF.createInstance(theLDMF.createPrototype(
239: Asset.class, "TestExp"));
240: theAggAsset = theLDMF.createInstance(theLDMF.createPrototype(
241: Asset.class, "TestAgg"));
242: theAllocAsset = theLDMF.createInstance(theLDMF.createPrototype(
243: Asset.class, "TestAlloc"));
244: publishAdd(theRootAsset);
245: publishAdd(theExpAsset);
246: publishAdd(theAggAsset);
247: publishAdd(theAllocAsset);
248: selfOrgs = (IncrementalSubscription) subscribe(new UnaryPredicate() {
249: public boolean execute(Object o) {
250: if (o instanceof Entity) {
251: return ((Entity) o).isSelf();
252: }
253: return false;
254: }
255: });
256: if (!useProvider)
257: setupSubscriptions2();
258: }
259:
260: private void setupSubscriptions2() {
261: mpTasks = new Vector[N_SUBTYPES];
262: for (int i = 0; i < mpTasks.length; i++) {
263: mpTasks[i] = new Vector();
264: }
265: tasksToExpand = (IncrementalSubscription) subscribe(expandPredicate);
266: tasksToAggregate = (IncrementalSubscription) subscribe(aggregatePredicate);
267: tasksToAllocateLocally = (IncrementalSubscription) subscribe(allocateLocallyPredicate);
268: tasksToAllocateRemotely = (IncrementalSubscription) subscribe(allocateRemotelyPredicate);
269: testEnd = currentTimeMillis() + testDuration;
270: setNewRootTimer();
271: if (!Double.isNaN(clockRate)) {
272: getDemoControlService().setSocietyTimeRate(clockRate);
273: }
274: }
275:
276: public void execute() {
277: if (logger.isDebugEnabled())
278: logger.debug("TestDeletionPlugin.execute() at "
279: + dateFormat.format(new Date(currentTimeMillis())));
280: long startTime = currentTimeMillis();
281: if (useProvider) {
282: if (provider == null) {
283: if (selfOrgs.hasChanged()) {
284: if (selfOrg == null) {
285: checkSelfOrgs(selfOrgs.getAddedList());
286: }
287: if (selfOrg == null)
288: return;
289: checkProvider();
290: }
291: }
292: if (provider == null)
293: return;
294: }
295: if (tasksToExpand.hasChanged()) {
296: handleExpTasksAdded(tasksToExpand.getAddedList());
297: handleExpTasksChanged(tasksToExpand.getChangedList());
298: handleExpTasksRemoved(tasksToExpand.getRemovedList());
299: }
300: if (tasksToAggregate.hasChanged()) {
301: handleSubTasksAdded(tasksToAggregate.getAddedList());
302: handleSubTasksChanged(tasksToAggregate.getChangedList());
303: handleSubTasksRemoved(tasksToAggregate.getRemovedList());
304: }
305: if (tasksToAllocateLocally.hasChanged()) {
306: handleAggTasksAdded(tasksToAllocateLocally.getAddedList(),
307: false);
308: handleAggTasksChanged(tasksToAllocateLocally
309: .getChangedList(), false);
310: handleAggTasksRemoved(tasksToAllocateLocally
311: .getRemovedList(), false);
312: }
313: if (tasksToAllocateRemotely.hasChanged()) {
314: handleAggTasksAdded(tasksToAllocateRemotely.getAddedList(),
315: true);
316: handleAggTasksChanged(tasksToAllocateRemotely
317: .getChangedList(), true);
318: handleAggTasksRemoved(tasksToAllocateRemotely
319: .getRemovedList(), true);
320: }
321:
322: if (newRootTimer != null && newRootTimer.hasExpired()) {
323: newRootTimer = null;
324: addRootTask();
325: rootCount++;
326: setNewRootTimer();
327: }
328: long endTime = currentTimeMillis();
329: long elapsed = endTime - startTime;
330: if (elapsed > maxElapsed) {
331: if (logger.isDebugEnabled())
332: logger.debug("time to run execute(): " + elapsed);
333: maxElapsed = elapsed;
334: }
335: }
336:
337: private long maxElapsed = 0L;
338:
339: private void checkSelfOrgs(Enumeration orgs) {
340: if (orgs.hasMoreElements()) {
341: selfOrg = (Entity) orgs.nextElement();
342: }
343: }
344:
345: private void checkProvider() {
346: Collection c = selfOrg.getRelationshipSchedule()
347: .getMatchingRelationships(testProviderRole);
348: if (c.size() > 0) {
349: Relationship relationship = (Relationship) c.iterator()
350: .next();
351: if (relationship.getRoleA().equals(testProviderRole)) {
352: provider = (Entity) relationship.getA();
353: } else {
354: provider = (Entity) relationship.getB();
355: }
356: setupSubscriptions2(); // Ready to go
357: }
358: }
359:
360: private long randomLong(long min, long max) {
361: return min + (long) (random.nextDouble() * (max - min));
362: }
363:
364: private void setNewRootTimer() {
365: if ((testDuration <= 0L || currentTimeMillis() < testEnd)
366: && (nRoots < 0 || rootCount < nRoots)) {
367: long interval = randomLong(minInterTaskInterval,
368: maxInterTaskInterval);
369: newRootTimer = wakeAfter(interval);
370: if (logger.isDebugEnabled())
371: logger.debug("Next wakeup after "
372: + (interval / 3600000.0) + " hours");
373: } else {
374: if (logger.isDebugEnabled())
375: logger.debug("No wakeup: " + testDuration + ", "
376: + nRoots);
377: }
378: }
379:
380: private void handleExpTasksAdded(Enumeration tasks) {
381: while (tasks.hasMoreElements()) {
382: Task expTask = (Task) tasks.nextElement();
383: try {
384: checkTaskValid(expTask);
385: if (logger.isDebugEnabled())
386: logger.debug("Exp task added: " + format(expTask));
387: expandTask(expTask);
388: } catch (RuntimeException re) {
389: if (logger.isErrorEnabled())
390: logger.error("handleExpTasksAdded: " + re);
391: failTask(expTask);
392: }
393: }
394: }
395:
396: private void handleExpTasksChanged(Enumeration tasks) {
397: while (tasks.hasMoreElements()) {
398: Task expTask = (Task) tasks.nextElement();
399: try {
400: checkTaskValid(expTask);
401: if (logger.isDebugEnabled())
402: logger
403: .debug("Exp task changed: "
404: + format(expTask));
405: } catch (RuntimeException re) {
406: if (logger.isErrorEnabled())
407: logger.error("handleExpTasksChanged: " + re);
408: }
409: }
410: }
411:
412: private void handleExpTasksRemoved(Enumeration tasks) {
413: while (tasks.hasMoreElements()) {
414: Task expTask = (Task) tasks.nextElement();
415: if (logger.isDebugEnabled())
416: logger.debug("Exp task removed: " + format(expTask));
417: // There's nothing to do
418: }
419: }
420:
421: private void handleSubTasksAdded(Enumeration tasks) {
422: while (tasks.hasMoreElements()) {
423: Task subTask = (Task) tasks.nextElement();
424: try {
425: checkTaskValid(subTask);
426: if (logger.isDebugEnabled())
427: logger.debug("subTask added: " + format(subTask));
428: aggregateSubtask(subTask);
429: } catch (RuntimeException re) {
430: if (logger.isErrorEnabled())
431: logger.error("handleSubTasksAdded: " + re);
432: failTask(subTask);
433: }
434: }
435: }
436:
437: private void handleSubTasksChanged(Enumeration tasks) {
438: while (tasks.hasMoreElements()) {
439: Task subTask = (Task) tasks.nextElement();
440: try {
441: checkTaskValid(subTask);
442: if (logger.isDebugEnabled())
443: logger.debug("subTask changed: " + format(subTask));
444: } catch (RuntimeException re) {
445: if (logger.isErrorEnabled())
446: logger.error("handleSubTasksChanged: " + re);
447: }
448: }
449: }
450:
451: private void handleSubTasksRemoved(Enumeration tasks) {
452: while (tasks.hasMoreElements()) {
453: Task subTask = (Task) tasks.nextElement();
454: if (logger.isDebugEnabled())
455: logger.debug("subTask removed:. " + format(subTask));
456: }
457: }
458:
459: private void handleAggTasksAdded(Enumeration tasks, boolean remote) {
460: while (tasks.hasMoreElements()) {
461: Task aggTask = (Task) tasks.nextElement();
462: try {
463: checkTaskValid(aggTask);
464: if (logger.isDebugEnabled())
465: logger.debug("aggTask added: " + format(aggTask));
466: allocateAggtask(aggTask, remote);
467: } catch (RuntimeException re) {
468: if (logger.isErrorEnabled())
469: logger.error("handleAggTasksAdded: " + re);
470: failTask(aggTask);
471: }
472: }
473: }
474:
475: private void handleAggTasksChanged(Enumeration tasks, boolean remote) {
476: while (tasks.hasMoreElements()) {
477: Task aggTask = (Task) tasks.nextElement();
478: try {
479: checkTaskValid(aggTask);
480: if (logger.isDebugEnabled())
481: logger.debug("aggTask changed: " + format(aggTask));
482: reallocateAggtask(aggTask, remote);
483: } catch (RuntimeException re) {
484: if (logger.isErrorEnabled())
485: logger.error("handleAggTasksChanged: " + re);
486: }
487: }
488: }
489:
490: private void handleAggTasksRemoved(Enumeration tasks, boolean remote) {
491: while (tasks.hasMoreElements()) {
492: Task aggTask = (Task) tasks.nextElement();
493: int subtype = getSubtype(aggTask);
494: mpTasks[subtype].remove(aggTask);
495: advanceScheduleStartTime(aggTask, remote);
496: }
497: }
498:
499: private void checkTaskValid(Task task) {
500: Date date = task.getCommitmentDate();
501: long t;
502: if (date != null) {
503: t = date.getTime();
504: } else {
505: try {
506: t = PluginHelper.getStartTime(task);
507: } catch (IllegalArgumentException iae) {
508: try {
509: t = PluginHelper.getEndTime(task);
510: } catch (IllegalArgumentException iae2) {
511: t = -1L;
512: }
513: }
514: }
515: if (t == -1L) {
516: throw new RuntimeException("Task has no valid time");
517: }
518: long now = currentTimeMillis();
519: if (now >= t) {
520: throw new RuntimeException(dateFormat.format(new Date(now))
521: + " is past the commitment time of: "
522: + format(task));
523: }
524: }
525:
526: /**
527: * Tasks are expanded into an number of subtasks. Constraints are
528: * erected between the tasks restricting them to strictly
529: * sequential execution. The duration of each subtask is between
530: * 50% and 100% of equal fractions of the parent task duration.
531: **/
532: private void expandTask(Task expTask) {
533: int nsubs = getSubtaskCount(expTask);
534: long parentDuration = getDuration(expTask);
535: long nominalDuration = parentDuration / nsubs;
536: long parentStart = PluginHelper.getStartTime(expTask);
537: long startTime = parentStart;
538: Vector subs = new Vector(nsubs);
539: Vector constraints = new Vector(nsubs + 1);
540: Task previousTask = null;
541: for (int i = 0; i < nsubs; i++) {
542: long duration = (long) (random.nextDouble() * nominalDuration);
543: NewTask subtask = createTask(testDeletionAggregate,
544: getLevel(expTask), i, theExpAsset, startTime,
545: startTime + nominalDuration, duration);
546: publishAdd(subtask);
547: startTime += nominalDuration;
548: subs.addElement(subtask);
549: if (previousTask == null) {
550: NewConstraint constraint = theLDMF.newConstraint();
551: constraint.setConstrainingTask(expTask);
552: constraint.setConstrainingAspect(AspectType.START_TIME);
553: constraint.setConstrainedTask(subtask);
554: constraint.setConstrainedAspect(AspectType.START_TIME);
555: constraint.setConstraintOrder(Constraint.AFTER);
556: constraints.addElement(constraint);
557: } else {
558: NewConstraint constraint = theLDMF.newConstraint();
559: constraint.setConstrainingTask(previousTask);
560: constraint.setConstrainingAspect(AspectType.END_TIME);
561: constraint.setConstrainedTask(subtask);
562: constraint.setConstrainedAspect(AspectType.START_TIME);
563: constraint.setConstraintOrder(Constraint.AFTER);
564: constraints.addElement(constraint);
565: }
566: previousTask = subtask;
567: }
568: NewConstraint constraint = theLDMF.newConstraint();
569: constraint.setConstrainingTask(expTask);
570: constraint.setConstrainingAspect(AspectType.END_TIME);
571: constraint.setConstrainedTask(previousTask);
572: constraint.setConstrainedAspect(AspectType.END_TIME);
573: constraint.setConstraintOrder(Constraint.BEFORE);
574: constraints.addElement(constraint);
575: AllocationResult ar = PluginHelper
576: .createEstimatedAllocationResult(expTask, theLDMF, 1.0,
577: true);
578: Expansion exp = PluginHelper.wireExpansion(expTask, subs,
579: theLDMF, ar);
580: NewWorkflow wf = (NewWorkflow) exp.getWorkflow();
581: wf.setConstraints(constraints.elements());
582: publishAdd(exp);
583: }
584:
585: private void failTask(Task task) {
586: AllocationResult ar = PluginHelper
587: .createEstimatedAllocationResult(task, theLDMF, 1.0,
588: false);
589: Disposition disp = theLDMF.createFailedDisposition(task
590: .getPlan(), task, ar);
591: publishAdd(disp);
592: }
593:
594: /**
595: * Find an aggregation for which the timespan can accomodate the
596: * subtask. If a suitable aggregation is not found, create a new
597: * one. A suitable aggregation is one for which all tasks fall
598: * completely within an AGGREGATION_PERIOD of time. That is, the
599: * interval between the earliest start time and the latest end
600: * time does not exceed AGGREGATION_PERIOD.
601: **/
602: private void aggregateSubtask(Task subtask) {
603: int subtype = getSubtype(subtask);
604: long startTime = PluginHelper.getStartTime(subtask);
605: long endTime = PluginHelper.getEndTime(subtask);
606: long now = currentTimeMillis();
607: long minTime = now + 2 * ONE_DAY;
608: if (startTime < minTime) {
609: if (logger.isDebugEnabled())
610: logger.debug("subtask starts too soon after "
611: + dateFormat.format(new Date(now)) + ": "
612: + format(subtask));
613: failTask(subtask);
614: return;
615: }
616: for (Iterator i = mpTasks[subtype].iterator(); i.hasNext();) {
617: NewMPTask mpTask = (NewMPTask) i.next();
618: long mpStartTime = PluginHelper.getStartTime(mpTask);
619: if (mpStartTime > minTime) {
620: continue; // Can't use if about to start
621: }
622: long mpEndTime = PluginHelper.getEndTime(mpTask);
623: if (mpStartTime + AGGREGATION_PERIOD > endTime
624: && mpEndTime - AGGREGATION_PERIOD < startTime) {
625: createAggregation(subtask, mpTask);
626: return;
627: }
628: }
629: NewMPTask mpTask = createMPTask(testDeletionExpand,
630: getLevel(subtask) + 1, subtype, theAggAsset, startTime,
631: endTime, endTime - startTime);
632: mpTasks[subtype].add(mpTask);
633: publishAdd(mpTask);
634: createAggregation(subtask, mpTask);
635: }
636:
637: private void createAggregation(Task subtask, NewMPTask mpTask) {
638: long startTime = PluginHelper.getStartTime(subtask);
639: if (startTime < PluginHelper.getStartTime(mpTask)) {
640: setStartTimePreference(mpTask, startTime);
641: }
642: long endTime = PluginHelper.getEndTime(subtask);
643: if (endTime > PluginHelper.getEndTime(mpTask)) {
644: setEndTimePreference(mpTask, endTime);
645: }
646: AllocationResult ar = PluginHelper
647: .createEstimatedAllocationResult(subtask, theLDMF, 1.0,
648: true);
649: Aggregation agg = PluginHelper.wireAggregation(subtask, mpTask,
650: theLDMF, ar);
651: publishChange(mpTask);
652: publishAdd(agg);
653: }
654:
655: private void setStartTimePreference(NewTask mpTask,
656: long newStartTime) {
657: ScoringFunction sf;
658: Preference pref;
659: sf = ScoringFunction.createStrictlyAtValue(AspectValue
660: .newAspectValue(AspectType.START_TIME, newStartTime));
661: pref = theLDMF.newPreference(AspectType.START_TIME, sf);
662: mpTask.setPreference(pref);
663: // mpTask.setCommitmentDate(new Date(newStartTime));
664:
665: }
666:
667: private void setEndTimePreference(NewTask mpTask, long newEndTime) {
668: ScoringFunction sf;
669: Preference pref;
670: sf = ScoringFunction.createStrictlyAtValue(AspectValue
671: .newAspectValue(AspectType.END_TIME, newEndTime));
672: pref = theLDMF.newPreference(AspectType.END_TIME, sf);
673: mpTask.setPreference(pref);
674: }
675:
676: private void advanceScheduleStartTime(Task task, boolean remote) {
677: }
678:
679: private int getLevel(Task task) {
680: PrepositionalPhrase pp = task.getPrepositionalPhrase(LEVEL);
681: if (pp == null) {
682: if (logger.isDebugEnabled())
683: logger.debug("No LEVEL for " + format(task));
684: return 0;
685: }
686: Integer io = (Integer) pp.getIndirectObject();
687: return io.intValue();
688: }
689:
690: private int getSubtype(Task task) {
691: PrepositionalPhrase pp = task.getPrepositionalPhrase(SUBTYPE);
692: Integer io = (Integer) pp.getIndirectObject();
693: return io.intValue();
694: }
695:
696: private static long getDuration(Task task) {
697: PrepositionalPhrase pp = task.getPrepositionalPhrase(DURATION);
698: Long io = (Long) pp.getIndirectObject();
699: return io.longValue();
700: }
701:
702: private static int getSubtaskCount(Task task) {
703: return N_SUBTYPES;
704: }
705:
706: private void reallocateAggtask(Task subtask, boolean remote) {
707: AllocationResult ar = PluginHelper
708: .createEstimatedAllocationResult(subtask, theLDMF, 1.0,
709: true);
710: Allocation alloc = (Allocation) subtask.getPlanElement();
711: alloc.setEstimatedResult(ar);
712: publishChange(alloc);
713: }
714:
715: private void allocateAggtask(Task subtask, boolean remote) {
716: Asset asset;
717: if (remote) {
718: asset = provider;
719: if (logger.isDebugEnabled())
720: logger.debug("Using provider " + provider);
721: } else {
722: asset = theAllocAsset;
723: }
724: if (asset == null)
725: return; // Wait 'til out provider checks reports for service
726: AllocationResult ar = PluginHelper
727: .createEstimatedAllocationResult(subtask, theLDMF, 1.0,
728: true);
729: Allocation alloc = theLDMF.createAllocation(subtask.getPlan(),
730: subtask, asset, ar, testProviderRole);
731: publishAdd(alloc);
732: }
733:
734: private NewMPTask createMPTask(Verb verb, int level, int subtype,
735: Asset asset, long startTime, long endTime, long duration) {
736: NewMPTask task = theLDMF.newMPTask();
737: fillTask(task, verb, level, subtype, asset, startTime, endTime,
738: duration);
739: NewComposition composition = theLDMF.newComposition();
740: composition.setCombinedTask(task);
741: task.setComposition(composition);
742: return task;
743: }
744:
745: private NewTask createTask(Verb verb, int level, int subtype,
746: Asset asset, long startTime, long endTime, long duration) {
747: NewTask task = theLDMF.newTask();
748: fillTask(task, verb, level, subtype, asset, startTime, endTime,
749: duration);
750: return task;
751: }
752:
753: private void fillTask(NewTask task, Verb verb, int level,
754: int subtype, Asset asset, long startTime, long endTime,
755: long duration) {
756: task.setVerb(verb);
757: NewPrepositionalPhrase pp;
758: Vector phrases = new Vector(3);
759:
760: pp = theLDMF.newPrepositionalPhrase();
761: pp.setPreposition(DURATION);
762: pp.setIndirectObject(new Long(duration));
763: phrases.addElement(pp);
764:
765: pp = theLDMF.newPrepositionalPhrase();
766: pp.setPreposition(LEVEL);
767: pp.setIndirectObject(new Integer(level));
768: phrases.addElement(pp);
769:
770: pp = theLDMF.newPrepositionalPhrase();
771: pp.setPreposition(SUBTYPE);
772: pp.setIndirectObject(new Integer(subtype));
773: phrases.addElement(pp);
774:
775: task.setPrepositionalPhrases(phrases.elements());
776: task.setDirectObject(asset);
777: // task.setCommitmentDate(new Date(startTime));
778: ScoringFunction sf;
779: Preference pref;
780: long slop = ((endTime - startTime) - duration) / 2L;
781: if (slop <= 0) {
782: sf = ScoringFunction.createStrictlyAtValue(AspectValue
783: .newAspectValue(AspectType.START_TIME, startTime));
784: } else {
785: double slope = 1.0 / slop; // Slope such that score reaches 1.0 in slop msec
786: sf = new ScoringFunction.AboveScoringFunction(AspectValue
787: .newAspectValue(AspectType.START_TIME, startTime),
788: slope);
789: }
790: pref = theLDMF.newPreference(AspectType.START_TIME, sf);
791: task.setPreference(pref);
792: if (slop <= 0) {
793: sf = ScoringFunction.createStrictlyAtValue(AspectValue
794: .newAspectValue(AspectType.END_TIME, endTime));
795: } else {
796: double slope = 1.0 / slop; // Slope such that score reaches 1.0 in slop msec
797: sf = new ScoringFunction.BelowScoringFunction(AspectValue
798: .newAspectValue(AspectType.END_TIME, endTime),
799: slope);
800: }
801: pref = theLDMF.newPreference(AspectType.END_TIME, sf);
802: task.setPreference(pref);
803: task.addObservableAspect(AspectType.START_TIME);
804: task.addObservableAspect(AspectType.END_TIME);
805: }
806:
807: private void addRootTask() {
808: long startTime = currentTimeMillis()
809: + randomLong(minRootTaskDelay, maxRootTaskDelay);
810: long duration = randomLong(minRootTaskDuration,
811: maxRootTaskDuration);
812: long endTime = startTime + 2L * duration;
813: NewTask task = createTask(testDeletionExpand, level, TYPE_ROOT,
814: theRootAsset, startTime, endTime, duration);
815: if (logger.isDebugEnabled())
816: logger.debug("Adding " + format(task));
817: publishAdd(task);
818: }
819:
820: private static DateFormat dateFormat = new SimpleDateFormat(
821: "yyyy/MM/dd HHmm");
822:
823: private String format(Task task) {
824: return task.getDirectObject().getTypeIdentificationPG()
825: .getTypeIdentification()
826: + ", level="
827: + getLevel(task)
828: + ", subtype="
829: + getSubtype(task)
830: + ", start="
831: + dateFormat.format(new Date(PluginHelper
832: .getStartTime(task)))
833: + ", end="
834: + dateFormat.format(new Date(PluginHelper
835: .getEndTime(task)));
836: }
837: }
|