Package SimPy :: Module SimulationTrace
[hide private]
[frames] | no frames]

Source Code for Module SimPy.SimulationTrace

  1  #!/usr / bin / env python 
  2  # coding=utf-8 
  3  # $Revision: 444 $ $Date: 2010-04-02 05:59:43 +0200 (Fri, 02 Apr 2010) $ kgm 
  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   
43 -def trace_dispatch(trace, command, func):
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
54 -class SimulationTrace(Simulation):
55 - def __init__(self):
56 Simulation.__init__(self) 57 self.trace = Trace(sim=self) 58 # Trace method to be called on _post calls. 59 self._post_tracing = None 60 61 # We use our own instance of the command dictionary. 62 self._dispatch = dict(Simulation._dispatch) 63 64 # Now wrap all commands in a tracing call. 65 for command, func in self._dispatch.items(): 66 self._dispatch[command] = trace_dispatch(self.trace, command, func)
67
68 - def initialize(self):
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):
78 # Activate _post tracing. 79 self._post_tracing = self.trace.recordActivate 80 Simulation.activate(self, obj, process, at, delay, prior) 81 self._post_tracing = None
82
83 - def reactivate( 84 self, obj, at='undefined', delay='undefined', prior=False):
85 # Activate _post tracing. 86 self._post_tracing = self.trace.recordReactivate 87 Simulation.reactivate(self, obj, at, delay, prior) 88 self._post_tracing = None
89
90 - def _terminate(self, process):
91 self.trace.tterminated(process) 92 Simulation._terminate(self, process)
93
94 - def simulate(self, until=0):
95 try: 96 return Simulation.simulate(self, until) 97 finally: 98 if not(self.trace.outfile is sys.stdout): 99 self.trace.outfile.close()
100
101 -class Trace(Lister):
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):
111 112 Trace.commandsproc={hold:Trace.thold, passivate:Trace.tpassivate, 113 request:Trace.trequest, release:Trace.trelease, 114 waitevent:Trace.twaitevent, 115 queueevent:Trace.tqueueevent, 116 waituntil:Trace.twaituntil, 117 get:Trace.tget, put:Trace.tput} 118 if sim is None: sim=Globals.sim 119 self.sim=sim 120 self.start = start 121 self.end = end 122 self.toTrace = toTrace 123 self.tracego = True 124 self.outfile = outfile 125 self._comment = None
126
127 - def treset(self):
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
143 - def tchange(self,**kmvar):
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
154 - def tstart(self):
155 self.tracego = True
156
157 - def tstop(self):
158 self.tracego = False
159
160 - def ifTrace(self, cond):
161 if self.tracego and (self.start <= self.sim.now() <= self.end)\ 162 and cond: 163 return True
164
165 - def thold(self, par):
166 try: 167 return 'delay: %s'%par[0][2] 168 except: 169 return 'delay: 0'
170 thold = classmethod(thold) 171
172 - def trequest(self, par):
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
183 - def trelease(self, par):
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
190 - def tpassivate(self, par):
191 return ""
192 tpassivate = classmethod(tpassivate) 193
194 - def tactivate(self, par):
195 pass
196 tactivate = classmethod(tactivate) 197
198 - def twaitevent(self, par):
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
207 - def tqueueevent(self, par):
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
216 - def tsignal(self, evt):
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
224 - def twaituntil(self, par):
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
274 - def recordEvent(self, command, whole):
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
298 - def recordInterrupt(self, who, victim):
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
306 - def recordCancel(self, who, victim):
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
314 - def recordActivate(self, who, when, prior):
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
322 - def recordReactivate(self, who, when, prior):
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
330 - def recordSignal(self, evt):
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
338 - def tterminated(self, who):
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):
347 self._comment = par
348 349 # For backward compatibility 350 Globals.sim = SimulationTrace() 351 trace = Globals.sim.trace 352 step = Globals.sim.step 353 peek = Globals.sim.peek 354 # End backward compatibility 355 356 if __name__ == '__main__': 357 print 'SimPy.SimulationTrace %s' %__version__ 358 ############# Test / demo functions #############
359 - def test_demo():
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
447 - def test_interrupt():
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) # breakdowns only during operation 464 yield hold, self, repairduration 465 print self.sim.now(),' repaired' 466 else: 467 break # no breakdown, ergo bus arrived 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
491 - def testSimEvents():
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
546 - def testwaituntil():
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 #rest 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 ## TEST COMPOUND 'YIELD REQUEST' COMMANDS 598 ## ------------------------------------------------------------- 599 600 ## ------------------------------------------------------------- 601 ## TEST 'yield (request, self, res),(hold, self, delay)' 602 ## == timeout renege 603 ## ------------------------------------------------------------- 604
605 - class JobTO(Process):
606 """ Job class for testing timeout reneging 607 """
608 - def __init__(self, server = None, name = '',sim=None):
609 Process.__init__(self, name,sim=sim) 610 self.res = server 611 self.gotResource = 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
623 - def testNoTimeout():
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
642 - def testTimeout1():
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
661 - def testTimeout2():
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 ## TEST 'yield (request, self, res),(waitevent, self, event)' 682 ## == event renege 683 ## ------------------------------------------------------------------
684 - class JobEvt(Process):
685 """ Job class for testing event reneging 686 """
687 - def __init__(self, server = None, name = '',sim=None):
688 Process.__init__(self, name,sim=sim) 689 self.res = server 690 self.gotResource = 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
701 - class JobEvtMulti(Process):
702 """ Job class for testing event reneging with multi - event lists 703 """
704 - def __init__(self, server = None, name = '',sim=None):
705 Process.__init__(self, name,sim=sim) 706 self.res = server 707 self.gotResource = 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
718 - class FireEvent(Process):
719 """Fires reneging event 720 """
721 - def __init__(self,**vars):
722 Process.__init__(self,**vars)
723 - def fire(self, fireDelay, event):
724 yield hold, self, fireDelay 725 event.signal()
726
727 - def testNoEvent():
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) #never gets fired 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 # Both jobs should get server (in sequence) 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
747 - def testWaitEvent1():
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 # Job_1 should get server, Job_2 renege 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
770 - def testWaitEvent2():
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 #for both events 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 # Job_1 should get server, Job_2 should renege 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