~divmod-dev/divmod.org/1304710-storeless-adapter

« back to all changes in this revision

Viewing changes to Axiom/axiom/scheduler.py

  • Committer: glyph
  • Date: 2005-07-28 22:09:16 UTC
  • Revision ID: svn-v4:866e43f7-fbfc-0310-8f2a-ec88d1da2979:trunk:2
move this repository to a more official-looking URL

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# -*- test-case-name: axiom.test.test_scheduler -*-
 
2
from twisted.internet import reactor
 
3
 
 
4
from twisted.application.service import Service, IService
 
5
 
 
6
from axiom.item import Item
 
7
from axiom.attributes import timestamp, reference, text, integer, inmemory
 
8
from axiom.extime import Time
 
9
 
 
10
from axiom.slotmachine import Attribute
 
11
 
 
12
class TimedEvent(Item):
 
13
    typeName = 'timed_event'
 
14
    schemaVersion = 1
 
15
 
 
16
    time = timestamp(indexed=True)
 
17
    runnable = reference()
 
18
 
 
19
class Scheduler(Item, Service):
 
20
 
 
21
    typeName = 'scheduler'
 
22
    schemaVersion = 1
 
23
 
 
24
    parent = inmemory()
 
25
    running = inmemory()
 
26
    name = inmemory()
 
27
    timer = inmemory()
 
28
 
 
29
    eventsRun = integer()
 
30
    lastEventAt = timestamp()
 
31
    nextEventAt = timestamp()
 
32
 
 
33
    def __subinit__(self, **kw):
 
34
        super(Scheduler, self).__subinit__(**kw)
 
35
        self.timer = None
 
36
        self.running = False
 
37
 
 
38
    def __init__(self, **kw):
 
39
        super(Scheduler, self).__init__(**kw)
 
40
        self.eventsRun = 0
 
41
        self.lastEventAt = None
 
42
        self.nextEventAt = None
 
43
 
 
44
    def install(self):
 
45
        self.store.powerUp(self, IService)
 
46
 
 
47
    def now(self):
 
48
        # testing hook
 
49
        return Time()
 
50
 
 
51
    def callLater(self, s, f, *a, **k):
 
52
        s = max(s, 0.00000001)
 
53
        return reactor.callLater(s, f, *a, **k)
 
54
 
 
55
    def tick(self):
 
56
        now = self.now()
 
57
        any = 0
 
58
        self.timer = None
 
59
        self.nextEventAt = None
 
60
        for event in self.store.query(TimedEvent,
 
61
                                      TimedEvent.time < now,
 
62
                                      sort=TimedEvent.time.ascending):
 
63
            self.eventsRun += 1
 
64
            newTime = event.runnable.run()
 
65
            if newTime is not None:
 
66
                event.time = newTime
 
67
            else:
 
68
                event.deleteFromStore()
 
69
            any = 1
 
70
        if any:
 
71
            self.lastEventAt = now
 
72
        x = list(
 
73
            self.store.query(TimedEvent, sort=TimedEvent.time.ascending, limit=1))
 
74
        if x:
 
75
            x = x[0]
 
76
            self.timer = self.callLater(
 
77
                x.time.asPOSIXTimestamp() - now.asPOSIXTimestamp(),
 
78
                self.store.transact, self.tick)
 
79
            self.nextEventAt = x.time
 
80
 
 
81
 
 
82
    def schedule(self, runnable, when):
 
83
        TimedEvent(store=self.store, time=when, runnable=runnable)
 
84
        if self.running:
 
85
            if self.timer is None:
 
86
                self.timer = self.callLater(0.00001, self.store.transact, self.tick)
 
87
 
 
88
    def startService(self):
 
89
        super(Scheduler, self).startService()
 
90
        self.store.transact(self.tick)
 
91
 
 
92
    def stopService(self):
 
93
        super(Scheduler, self).stopService()
 
94
        if hasattr(self, 'timer'):
 
95
            self.timer.cancel()
 
96
            self.timer = None