1
2
3
4 """SimulationTrace 2.1 Traces execution of SimPy models.
5 Implements SimPy Processes, Resources, Buffers, and the backbone simulation
6 scheduling by coroutine calls. Provides data collection through classes
7 Monitor and Tally.
8 Based on generators (Python 2.3 and later; not 3.0)
9
10 LICENSE:
11 Copyright (C) 2002, 2005, 2006, 2007, 2008 Klaus G. Muller, Tony Vignaux
12 mailto: kgmuller@xs4all.nl and Tony.Vignaux@vuw.ac.nz
13
14 This library is free software; you can redistribute it and / or
15 modify it under the terms of the GNU Lesser General Public
16 License as published by the Free Software Foundation; either
17 version 2.1 of the License, or (at your option) any later version.
18
19 This library is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 Lesser General Public License for more details.
23
24 You should have received a copy of the GNU Lesser General Public
25 License along with this library; if not, write to the Free Software
26 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 - 1307 USA
27 END OF LICENSE
28 """
29
30 from SimPy.Lister import *
31 from SimPy.Simulation import *
32
33
34 __TESTING = False
35 version = __version__ = '2.1 $Revision: 444 $ $Date: 2010-04-02 05:59:43 +0200 (Fri, 02 Apr 2010) $'
36 if __TESTING:
37 print 'SimPy.SimulationTrace %s' %__version__,
38 if __debug__:
39 print '__debug__ on'
40 else:
41 print
42
44 """
45 Returns a wrapper for ``func`` which will record the dispatch in the trace
46 log.
47 """
48 def dispatch(event):
49 func(event)
50 trace.recordEvent(command, event)
51
52 return dispatch
53
67
70
71
72 - def _post(self, what, at, prior=False):
73 if self._post_tracing is not None: self._post_tracing(what, at, prior)
74 Simulation._post(self, what, at, prior)
75
76 - def activate(
77 self, obj, process, at='undefined', delay='undefined', prior=False):
82
83 - def reactivate(
84 self, obj, at='undefined', delay='undefined', prior=False):
89
93
100
102 commands={hold:'hold', passivate:'passivate', request:'request', release:'release',
103 waitevent:'waitevent', queueevent:'queueevent', waituntil:'waituntil',
104 get:'get', put:'put'}
105
106 - def __init__(self, start = 0, end = 10000000000L, toTrace=\
107 ['hold', 'activate', 'cancel', 'reactivate', 'passivate', 'request',
108 'release', 'interrupt', 'terminated', 'waitevent', 'queueevent',
109 'signal', 'waituntil', 'put', 'get'
110 ],outfile = sys.stdout,sim=None):
126
128 Trace.commandsproc={hold:Trace.thold, passivate:Trace.tpassivate,
129 request:Trace.trequest, release:Trace.trelease,
130 waitevent:Trace.twaitevent,
131 queueevent:Trace.tqueueevent,
132 waituntil:Trace.twaituntil,
133 get:Trace.tget, put:Trace.tput}
134 self.start = 0
135 self.end = 10000000000L
136 self.toTrace = ['hold', 'activate', 'cancel', 'reactivate', 'passivate', 'request',
137 'release', 'interrupt', 'terminated', 'waitevent', 'queueevent',
138 'signal', 'waituntil', 'put', 'get']
139 self.tracego = True
140 self.outfile = sys.stdout
141 self._comment = None
142
144 for v in kmvar.keys():
145 if v == 'start':
146 self.start = kmvar[v]
147 elif v == 'end':
148 self.end = kmvar[v]
149 elif v == 'toTrace':
150 self.toTrace = kmvar[v]
151 elif v == 'outfile':
152 self.outfile = kmvar[v]
153
156
159
161 if self.tracego and (self.start <= self.sim.now() <= self.end)\
162 and cond:
163 return True
164
166 try:
167 return 'delay: %s'%par[0][2]
168 except:
169 return 'delay: 0'
170 thold = classmethod(thold)
171
173 res = par[0][2]
174 if len(par[0]) == 4:
175 priority = ' priority: ' + str(par[0][3])
176 else:
177 priority = ' priority: default'
178 wQ = [x.name for x in res.waitQ]
179 aQ = [x.name for x in res.activeQ]
180 return '<%s> %s \n. . .waitQ: %s \n. . .activeQ: %s' % (res.name, priority, wQ, aQ)
181 trequest = classmethod(trequest)
182
184 res = par[0][2]
185 wQ = [x.name for x in res.waitQ]
186 aQ = [x.name for x in res.activeQ]
187 return '<%s> \n. . .waitQ: %s \n. . .activeQ: %s' % (res.name, wQ, aQ)
188 trelease = classmethod(trelease)
189
192 tpassivate = classmethod(tpassivate)
193
196 tactivate = classmethod(tactivate)
197
199 evt = par[0][2]
200 if type(evt) == list or type(evt) == tuple:
201 enames = [x.name for x in evt]
202 return 'waits for events <%s > '%enames
203 else:
204 return 'waits for event <%s > '%evt.name
205 twaitevent = classmethod(twaitevent)
206
208 evt = par[0][2]
209 if type(evt) == list or type(evt) == tuple:
210 enames = [x.name for x in evt]
211 return 'queues for events <%s > '%enames
212 else:
213 return 'queues for event <%s > '%evt.name
214 tqueueevent = classmethod(tqueueevent)
215
217 wQ = [x.name for x in evt.waits]
218 qQ = [x.name for x in evt.queues]
219 return '<%s> \n. . . occurred: %s\n. . . waiting: %s\n. . . queueing: %s'\
220 %(evt.name, evt.occurred, wQ, qQ)
221 pass
222 tsignal = classmethod(tsignal)
223
225 condition = par[0][2]
226 return 'for condition <%s > '%condition.func_name
227 twaituntil = classmethod(twaituntil)
228
229 - def tget(self, par):
230 buff = par[0][2]
231 if len(par[0]) == 5:
232 priority = ' priority: ' + str(par[0][4])
233 else:
234 priority = ' priority: default'
235 if len(par[0]) == 3:
236 nrToGet = 1
237 else:
238 nrToGet = par[0][3]
239 toGet = 'to get: %s %s from' % (nrToGet, buff.unitName)
240 getQ = [x.name for x in buff.getQ]
241 putQ = [x.name for x in buff.putQ]
242 try:
243 inBuffer = buff.amount
244 except:
245 inBuffer = buff.nrBuffered
246 return '%s <%s> %s \n. . .getQ: %s \n. . .putQ: %s \n. . .in buffer: %s'\
247 %(toGet, buff.name, priority, getQ, putQ, inBuffer)
248 tget = classmethod(tget)
249
250 - def tput(self, par):
251 buff = par[0][2]
252 if len(par[0]) == 5:
253 priority = ' priority: ' + str(par[0][4])
254 else:
255 priority = ' priority: default'
256 if len(par[0]) == 3:
257 nrToPut = 1
258 else:
259 if type(par[0][3]) == type([]):
260 nrToPut = len(par[0][3])
261 else:
262 nrToPut = par[0][3]
263 getQ = [x.name for x in buff.getQ]
264 putQ = [x.name for x in buff.putQ]
265 toPut = 'to put: %s %s into' % (nrToPut, buff.unitName)
266 try:
267 inBuffer = buff.amount
268 except:
269 inBuffer = buff.nrBuffered
270 return '%s <%s> %s \n. . .getQ: %s \n. . .putQ: %s \n. . .in buffer: %s'\
271 %(toPut, buff.name, priority, getQ, putQ, inBuffer)
272 tput = classmethod(tput)
273
275 if self.ifTrace(Trace.commands[command] in self.toTrace):
276 if not type(whole[0][0]) == tuple:
277 print >> self.outfile, whole[0][1].sim.now(),\
278 Trace.commands[command],\
279 ' < ' + whole[0][1].name + ' > ',\
280 Trace.commandsproc[command](whole)
281 if self._comment:
282 print >> self.outfile, '----', self._comment
283 else:
284 print >> self.outfile, whole[0][0][1].sim.now(),\
285 Trace.commands[command],\
286 ' < ' + whole[0][0][1].name + ' > '+\
287 Trace.commandsproc[command](whole[0])
288 print >> self.outfile, '|| RENEGE COMMAND:'
289 command1 = whole[0][1][0]
290 print >> self.outfile, '||\t', Trace.commands[command1],\
291 ' < ' + whole[0][1][1].name + ' > ',\
292 Trace.commandsproc[command1]((whole[0][1],))
293 if self._comment:
294 print >> self.outfile, '----', self._comment
295
296 self._comment = None
297
299 if self.ifTrace('interrupt' in self.toTrace):
300 print >> self.outfile, '%s interrupt by: <%s > of: <%s >'\
301 %(who.sim.now(),who.name, victim.name)
302 if self._comment:
303 print >> self.outfile, '----', self._comment
304 self._comment = None
305
307 if self.ifTrace('cancel' in self.toTrace):
308 print >> self.outfile, '%s cancel by: <%s > of: <%s > '\
309 %(who.sim.now(),who.name, victim.name)
310 if self._comment:
311 print >> self.outfile, '----', self._comment
312 self._comment = None
313
315 if self.ifTrace('activate' in self.toTrace):
316 print >> self.outfile, '%s activate <%s > at time: %s prior: %s'\
317 %(who.sim.now(),who.name,when, prior)
318 if self._comment:
319 print >> self.outfile, '----', self._comment
320 self._comment = None
321
323 if self.ifTrace('reactivate' in self.toTrace):
324 print >> self.outfile, '%s reactivate <%s > time: %s prior: %s'\
325 %(who.sim.now(),who.name,when, prior)
326 if self._comment:
327 print >> self.outfile, '----', self._comment
328 self._comment = None
329
331 if self.ifTrace('signal' in self.toTrace):
332 print >> self.outfile, '%s event <%s > is signalled' \
333 %(evt.sim.now(),evt.name)
334 if self._comment:
335 print >> self.outfile, '----', self._comment
336 self._comment = None
337
339 if self.ifTrace('terminated' in self.toTrace):
340 print >> self.outfile, '%s <%s > terminated'\
341 %(who.sim.now(),who.name)
342 if self._comment:
343 print >> self.outfile, '----', self._comment
344 self._comment = None
345
346 - def ttext(self, par):
348
349
350 Globals.sim = SimulationTrace()
351 trace = Globals.sim.trace
352 step = Globals.sim.step
353 peek = Globals.sim.peek
354
355
356 if __name__ == '__main__':
357 print 'SimPy.SimulationTrace %s' %__version__
358
360 class Aa(Process):
361 sequIn = []
362 sequOut = []
363 def __init__(self, holdtime, name,sim=None):
364 Process.__init__(self, name,sim=sim)
365 self.holdtime = holdtime
366
367 def life(self, priority):
368 for i in range(1):
369 Aa.sequIn.append(self.name)
370 print self.sim.now(),rrr.name, 'waitQ:', len(rrr.waitQ),'activeQ:',\
371 len(rrr.activeQ)
372 print 'waitQ: ',[(k.name, k._priority[rrr]) for k in rrr.waitQ]
373 print 'activeQ: ',[(k.name, k._priority[rrr]) \
374 for k in rrr.activeQ]
375 assert rrr.n + len(rrr.activeQ) == rrr.capacity, \
376 'Inconsistent resource unit numbers'
377 print self.sim.now(),self.name, 'requests 1 ', rrr.unitName
378 yield request, self, rrr, priority
379 print self.sim.now(),self.name, 'has 1 ', rrr.unitName
380 print self.sim.now(),rrr.name, 'waitQ:', len(rrr.waitQ),'activeQ:',\
381 len(rrr.activeQ)
382 print self.sim.now(),rrr.name, 'waitQ:', len(rrr.waitQ),'activeQ:',\
383 len(rrr.activeQ)
384 assert rrr.n + len(rrr.activeQ) == rrr.capacity, \
385 'Inconsistent resource unit numbers'
386 yield hold, self, self.holdtime
387 print self.sim.now(),self.name, 'gives up 1', rrr.unitName
388 yield release, self, rrr
389 Aa.sequOut.append(self.name)
390 print self.sim.now(),self.name, 'has released 1 ', rrr.unitName
391 print 'waitQ: ',[(k.name, k._priority[rrr]) for k in rrr.waitQ]
392 print self.sim.now(),rrr.name, 'waitQ:', len(rrr.waitQ),'activeQ:',\
393 len(rrr.activeQ)
394 assert rrr.n + len(rrr.activeQ) == rrr.capacity, \
395 'Inconsistent resource unit numbers'
396
397 class Observer(Process):
398 def __init__(self,**vars):
399 Process.__init__(self,**vars)
400
401 def observe(self, step, processes, res):
402 while self.sim.now() < 11:
403 for i in processes:
404 print '++ %s process: %s: active:%s, passive:%s, terminated: %s, interrupted:%s, queuing:%s'\
405 %(self.sim.now(),i.name, i.active(),i.passive(),\
406 i.terminated(),i.interrupted(),i.queuing(res))
407 print
408 yield hold, self, step
409
410 print'\n+++test_demo output'
411 print '****First case == priority queue, resource service not preemptable'
412 s=SimulationTrace()
413 s.initialize()
414 rrr = Resource(5, name = 'Parking', unitName = 'space(s)', qType = PriorityQ,
415 preemptable = 0,sim=s)
416 procs = []
417 for i in range(10):
418 z = Aa(holdtime = i, name = 'Car ' + str(i),sim=s)
419 procs.append(z)
420 s.activate(z, z.life(priority = i))
421 o = Observer(sim=s)
422 s.activate(o, o.observe(1, procs, rrr))
423 a = s.simulate(until = 10000)
424 print a
425 print 'Input sequence: ', Aa.sequIn
426 print 'Output sequence: ', Aa.sequOut
427
428 print '\n****Second case == priority queue, resource service preemptable'
429 s=SimulationTrace()
430 s.initialize()
431 rrr = Resource(5, name = 'Parking', unitName = 'space(s)', qType = PriorityQ,
432 preemptable = 1,sim=s)
433 procs = []
434 for i in range(10):
435 z = Aa(holdtime = i, name = 'Car ' + str(i),sim=s)
436 procs.append(z)
437 s.activate(z, z.life(priority = i))
438 o = Observer(sim=s)
439 s.activate(o, o.observe(1, procs, rrr))
440 Aa.sequIn = []
441 Aa.sequOut = []
442 a = s.simulate(until = 10000)
443 print a
444 print 'Input sequence: ', Aa.sequIn
445 print 'Output sequence: ', Aa.sequOut
446
448 class Bus(Process):
449 def __init__(self, **vars):
450 Process.__init__(self, **vars)
451
452 def operate(self, repairduration = 0):
453 print self.sim.now(),'>> %s starts' % (self.name)
454 tripleft = 1000
455 while tripleft > 0:
456 yield hold, self, tripleft
457 if self.interrupted():
458 print 'interrupted by %s' %self.interruptCause.name
459 print '%s: %s breaks down ' %(now(),self.name)
460 tripleft = self.interruptLeft
461 self.interruptReset()
462 print 'tripleft ', tripleft
463 s.reactivate(br, delay = repairduration)
464 yield hold, self, repairduration
465 print self.sim.now(),' repaired'
466 else:
467 break
468 print self.sim.now(),'<< %s done' % (self.name)
469
470 class Breakdown(Process):
471 def __init__(self, myBus,sim=None):
472 Process.__init__(self, name = 'Breakdown ' + myBus.name,sim=sim)
473 self.bus = myBus
474
475 def breakBus(self, interval):
476
477 while True:
478 yield hold, self, interval
479 if self.bus.terminated(): break
480 self.interrupt(self.bus)
481
482 print'\n\n+++test_interrupt'
483 s=SimulationTrace()
484 s.initialize()
485 b = Bus(name='Bus 1',sim=s)
486 s.activate(b, b.operate(repairduration = 20))
487 br = Breakdown(b,sim=s)
488 s.activate(br, br.breakBus(200))
489 print s.simulate(until = 4000)
490
492 class Waiter(Process):
493 def __init__(self,**vars):
494 Process.__init__(self,**vars)
495 def waiting(self, theSignal):
496 while True:
497 yield waitevent, self, theSignal
498 print '%s: process \'%s\' continued after waiting for %s' %\
499 (self.sim.now(),self.name, theSignal.name)
500 yield queueevent, self, theSignal
501 print '%s: process \'%s\' continued after queueing for %s' % (now(),self.name, theSignal.name)
502
503 class ORWaiter(Process):
504 def __init__(self,**vars):
505 Process.__init__(self,**vars)
506 def waiting(self, signals):
507 while True:
508 yield waitevent, self, signals
509 print self.sim.now(),'one of %s signals occurred' %\
510 [x.name for x in signals]
511 print '\t%s (fired / param)'%\
512 [(x.name, x.signalparam) for x in self.eventsFired]
513 yield hold, self, 1
514
515 class Caller(Process):
516 def __init__(self,**vars):
517 Process.__init__(self,**vars)
518 def calling(self):
519 while True:
520 signal1.signal('wake up!')
521 print '%s: signal 1 has occurred'%now()
522 yield hold, self, 10
523 signal2.signal('and again')
524 signal2.signal('sig 2 again')
525 print '%s: signal1, signal2 have occurred'%now()
526 yield hold, self, 10
527 print'\n+++testSimEvents output'
528 s=SimulationTrace()
529 s.initialize()
530 signal1 = SimEvent('signal 1',sim=s)
531 signal2 = SimEvent('signal 2',sim=s)
532 signal1.signal('startup1')
533 signal2.signal('startup2')
534 w1 = Waiter(name='waiting for signal 1',sim=s)
535 s.activate(w1, w1.waiting(signal1))
536 w2 = Waiter(name='waiting for signal 2',sim=s)
537 s.activate(w2, w2.waiting(signal2))
538 w3 = Waiter(name='also waiting for signal 2',sim=s)
539 s.activate(w3, w3.waiting(signal2))
540 w4 = ORWaiter(name='waiting for either signal 1 or signal 2',sim=s)
541 s.activate(w4, w4.waiting([signal1, signal2]),prior = True)
542 c = Caller(name='Caller',sim=s)
543 s.activate(c, c.calling())
544 print s.simulate(until = 100)
545
547 """
548 Demo of waitUntil capability.
549
550 Scenario:
551 Three workers require sets of tools to do their jobs. Tools are shared,
552 scarce resources for which they compete.
553 """
554 class Worker(Process):
555 def __init__(self, name, heNeeds = [],sim=None):
556 Process.__init__(self, name,sim=sim)
557 self.heNeeds = heNeeds
558 def work(self):
559 def workerNeeds():
560 for item in self.heNeeds:
561 if item.n == 0:
562 return False
563 return True
564
565 while self.sim.now() < 8 * 60:
566 yield waituntil, self, workerNeeds
567 for item in self.heNeeds:
568 yield request, self, item
569 print '%s %s has %s and starts job' % (self.sim.now(),self.name,
570 [x.name for x in self.heNeeds])
571 yield hold, self, random.uniform(10, 30)
572 for item in self.heNeeds:
573 yield release, self, item
574 yield hold, self, 2
575
576 print '\n+++ nwaituntil demo output'
577 random.seed(12345)
578 s=SimulationTrace()
579 s.initialize()
580 brush = Resource(capacity = 1, name = 'brush',sim=s)
581 ladder = Resource(capacity = 2, name = 'ladder',sim=s)
582 hammer = Resource(capacity = 1, name = 'hammer',sim=s)
583 saw = Resource(capacity = 1, name = 'saw',sim=s)
584 painter = Worker('painter',[brush, ladder],sim=s)
585 s.activate(painter, painter.work())
586 roofer = Worker('roofer',[hammer, ladder, ladder],sim=s)
587 s.activate(roofer, roofer.work())
588 treeguy = Worker('treeguy',[saw, ladder],sim=s)
589 s.activate(treeguy, treeguy.work())
590 for who in (painter, roofer, treeguy):
591 print '%s needs %s for his job' %\
592 (who.name,[x.name for x in who.heNeeds])
593 print
594 print s.simulate(until = 9 * 60)
595
596
597
598
599
600
601
602
603
604
606 """ Job class for testing timeout reneging
607 """
608 - def __init__(self, server = None, name = '',sim=None):
612
613 - def execute(self, timeout, usetime):
614 yield (request, self, self.res),(hold, self, timeout)
615 if self.acquired(self.res):
616 self.gotResource = True
617 yield hold, self, usetime
618 yield release, self, self.res
619 else:
620 self.gotResource = False
621
622
624 """Test that resource gets acquired without timeout
625 """
626 s=SimulationTrace()
627 s.initialize()
628 res = Resource(name = 'Server', capacity = 1,sim=s)
629 usetime = 5
630 timeout = 1000000
631 j1 = JobTO(server = res, name = 'Job_1',sim=s)
632 s.activate(j1, j1.execute(timeout = timeout, usetime = usetime))
633 j2 = JobTO(server = res, name = 'Job_2',sim=s)
634 s.activate(j2, j2.execute(timeout = timeout, usetime = usetime))
635 s.simulate(until = 2 * usetime)
636 assert s.now() == 2 * usetime, 'time not == 2 * usetime'
637 assert j1.gotResource and j2.gotResource,\
638 'at least one job failed to get resource'
639 assert not (res.waitQ or res.activeQ),\
640 'job waiting or using resource'
641
643 """Test that timeout occurs when resource busy
644 """
645 s=SimulationTrace()
646 s.initialize()
647 res = Resource(name = 'Server', capacity = 1, monitored = True,sim=s)
648 usetime = 5
649 timeout = 3
650 j1 = JobTO(server = res, name = 'Job_1',sim=s)
651 s.activate(j1, j1.execute(timeout = timeout, usetime = usetime))
652 j2 = JobTO(server = res, name = 'Job_2',sim=s)
653 s.activate(j2, j2.execute(timeout = timeout, usetime = usetime))
654 s.simulate(until = 2 * usetime)
655 assert(s.now() == usetime),'time not == usetime'
656 assert(j1.gotResource),'Job_1 did not get resource'
657 assert(not j2.gotResource),'Job_2 did not renege'
658 assert not (res.waitQ or res.activeQ),\
659 'job waiting or using resource'
660
662 """Test that timeout occurs when resource has no capacity free
663 """
664 s=SimulationTrace()
665 s.initialize()
666 res = Resource(name = 'Server', capacity = 0,sim=s)
667 usetime = 5
668 timeout = 3
669 j1 = JobTO(server = res, name = 'Job_1',sim=s)
670 s.activate(j1, j1.execute(timeout = timeout, usetime = usetime))
671 j2 = JobTO(server = res, name = 'Job_2',sim=s)
672 s.activate(j2, j2.execute(timeout = timeout, usetime = usetime))
673 s.simulate(until = 2 * usetime)
674 assert s.now() == timeout, 'time %s not == timeout'%now()
675 assert not j1.gotResource, 'Job_1 got resource'
676 assert not j2.gotResource, 'Job_2 got resource'
677 assert not (res.waitQ or res.activeQ),\
678 'job waiting or using resource'
679
680
681
682
683
685 """ Job class for testing event reneging
686 """
687 - def __init__(self, server = None, name = '',sim=None):
691
692 - def execute(self, event, usetime):
693 yield (request, self, self.res),(waitevent, self, event)
694 if self.acquired(self.res):
695 self.gotResource = True
696 yield hold, self, usetime
697 yield release, self, self.res
698 else:
699 self.gotResource = False
700
702 """ Job class for testing event reneging with multi - event lists
703 """
704 - def __init__(self, server = None, name = '',sim=None):
708
709 - def execute(self, eventlist, usetime):
710 yield (request, self, self.res),(waitevent, self, eventlist)
711 if self.acquired(self.res):
712 self.gotResource = True
713 yield hold, self, usetime
714 yield release, self, self.res
715 else:
716 self.gotResource = False
717
719 """Fires reneging event
720 """
723 - def fire(self, fireDelay, event):
724 yield hold, self, fireDelay
725 event.signal()
726
728 """Test that processes acquire resource normally if no event fires
729 """
730 s=SimulationTrace()
731 s.initialize()
732 res = Resource(name = 'Server', capacity = 1,sim=s)
733 event = SimEvent(name='Renege_trigger',sim=s)
734 usetime = 5
735 j1 = JobEvt(server = res, name = 'Job_1',sim=s)
736 s.activate(j1, j1.execute(event = event, usetime = usetime))
737 j2 = JobEvt(server = res, name = 'Job_2',sim=s)
738 s.activate(j2, j2.execute(event = event, usetime = usetime))
739 s.simulate(until = 2 * usetime)
740
741 assert s.now() == 2 * usetime, 'time not == 2 * usetime'
742 assert j1.gotResource and j2.gotResource,\
743 'at least one job failed to get resource'
744 assert not (res.waitQ or res.activeQ),\
745 'job waiting or using resource'
746
748 """Test that signalled event leads to renege when resource busy
749 """
750 s=SimulationTrace()
751 s.initialize()
752 res = Resource(name = 'Server', capacity = 1,sim=s)
753 event = SimEvent('Renege_trigger',sim=s)
754 usetime = 5
755 eventtime = 1
756 j1 = JobEvt(server = res, name = 'Job_1',sim=s)
757 s.activate(j1, j1.execute(event = event, usetime = usetime))
758 j2 = JobEvt(server = res, name = 'Job_2',sim=s)
759 s.activate(j2, j2.execute(event = event, usetime = usetime))
760 f = FireEvent(name = 'FireEvent',sim=s)
761 s.activate(f, f.fire(fireDelay = eventtime, event = event))
762 s.simulate(until = 2 * usetime)
763
764 assert(s.now() == usetime),'time not == usetime'
765 assert(j1.gotResource),'Job_1 did not get resource'
766 assert(not j2.gotResource),'Job_2 did not renege'
767 assert not (res.waitQ or res.activeQ),\
768 'job waiting or using resource'
769
771 """Test that renege - triggering event can be one of an event list
772 """
773 s=SimulationTrace()
774 s.initialize()
775 res = Resource(name = 'Server', capacity = 1,sim=s)
776 event1 = SimEvent('Renege_trigger_1',sim=s)
777 event2 = SimEvent('Renege_trigger_2',sim=s)
778 usetime = 5
779 eventtime = 1
780 j1 = JobEvtMulti(server = res, name = 'Job_1',sim=s)
781 s.activate(j1, j1.execute(eventlist = [event1, event2],usetime = usetime))
782 j2 = JobEvtMulti(server = res, name = 'Job_2',sim=s)
783 s.activate(j2, j2.execute(eventlist = [event1, event2],usetime = usetime))
784 f1 = FireEvent(name = 'FireEvent_1',sim=s)
785 s.activate(f1, f1.fire(fireDelay = eventtime, event = event1))
786 f2 = FireEvent(name = 'FireEvent_2',sim=s)
787 s.activate(f2, f2.fire(fireDelay = eventtime, event = event2))
788 s.simulate(until = 2 * usetime)
789
790 assert(s.now() == usetime),'time not == usetime'
791 assert(j1.gotResource),'Job_1 did not get resource'
792 assert(not j2.gotResource),'Job_2 did not renege'
793 assert not (res.waitQ or res.activeQ),\
794 'job waiting or using resource'
795
796 testNoTimeout()
797 testTimeout1()
798 testTimeout2()
799 testNoEvent()
800 testWaitEvent1()
801 testWaitEvent2()
802 test_demo()
803 test_interrupt()
804 testSimEvents()
805 testwaituntil()
806