Contact: fumanchu@aminus.org

Log in as guest/dejavu to create tickets

root/branches/crazycache/dejavu/views.py

Revision 479 (checked in by fumanchu, 1 year ago)

Moved all content down into the new dejavu top-level folder.

  • Property svn:eol-style set to native
Line 
1 """OLAP Views and Snapshots (materialized views).
2
3 Notice in particular that Snapshot and View are _temporary_ Units.
4 Even when you memorize them, they won't be persistent unless you set
5 each instance's Expiration to None.
6 """
7
8 import datetime
9 import dejavu
10 from dejavu import errors, recur
11 from geniusql import logic
12
13
14 class TemporaryUnit(dejavu.Unit):
15    
16     Expiration = dejavu.UnitProperty(datetime.datetime)
17    
18     def on_recall(self):
19         if self.Expiration is not None:
20             if self.Expiration <= datetime.datetime.now():
21                 self.forget()
22                 raise errors.UnrecallableError
23             else:
24                 self.decay(minutes=15)
25    
26     def decay(self, **kw):
27         """decay(**kw) -> Set Expiration to now() + timedelta(**kw)."""
28         self.Expiration = datetime.datetime.now() + datetime.timedelta(**kw)
29
30
31 class TemporarySweeper(recur.Worker):
32     """A worker to sweep out expired TemporaryUnit's."""
33    
34     def work(self):
35         """Start a cycle of scheduled work."""
36         now = datetime.datetime.now()
37         f = lambda x: x.Expiration != None and x.Expiration <= now
38         box = self.store.new_sandbox()
39        
40         for cls in self.store.classes:
41             if issubclass(cls, TemporaryUnit):
42                 # Running box.recall will call TemporaryUnit.on_recall,
43                 # which should forget expired units.
44                 box.recall(cls, f)
45         box.flush_all()
46
47
48 class View(TemporaryUnit):
49     """A selector from (possibly multiple and/or aggregated) relations.
50     
51     When a View is called, it returns a Snapshot.
52     """
53    
54     Name = dejavu.UnitProperty()
55     Created = dejavu.UnitProperty(datetime.datetime)
56    
57     # The following are equivalent to:
58     # "SELECT Attributes FROM Relation WHERE Restriction"
59     Query = dejavu.UnitProperty(dejavu.Query)
60    
61     def __init__(self, Query=None, Created=None, **kwargs):
62         if Created is None:
63             Created = datetime.datetime.today()
64         if not isinstance(Query, dejavu.Query):
65             Query = dejavu.Query(*Query)
66         TemporaryUnit.__init__(self, Query=Query, Created=Created, **kwargs)
67    
68     def on_forget(self):
69         # Snapshots shouldn't persist past the life of their View.
70         for mv in self.Snapshot():
71             mv.forget()
72    
73     def __call__(self, name, store=None):
74         """Execute self and return a Snapshot."""
75         if store is None:
76             store = self.sandbox.store
77         newcls = store.insert_into(name, self.Query)
78         snap = Snapshot(ViewID=self.ID, ResultName=name)
79         snap.decay(minutes=15)
80         return snap
81     results = __call__
82    
83     def __copy__(self):
84         view = TemporaryUnit.__copy__(self)
85         view.Name = "Copy of %s" % self.Name
86         view.Created = datetime.datetime.now()
87         return view
88
89
90 class Snapshot(TemporaryUnit):
91     """A materialized view; the result set obtained by calling a View.
92     
93     Each Snapshot Unit instance possesses its own additional, dynamic
94     unit class which contains the actual result data. The 'ResultName'
95     attribute of the Snapshot must match the class name of the actual
96     result data.
97     """
98    
99     ViewID = dejavu.UnitProperty(int, index=True)
100     Timestamp = dejavu.UnitProperty(datetime.datetime)
101     ResultName = dejavu.UnitProperty()
102    
103     def __init__(self, Timestamp=None, **kwargs):
104         if Timestamp is None:
105             Timestamp = datetime.datetime.now()
106         TemporaryUnit.__init__(self, Timestamp=Timestamp, **kwargs)
107    
108     def unitclass(self, store=None):
109         if store is None:
110             store = self.sandbox.store
111         try:
112             return store.class_by_name(self.ResultName)
113         except KeyError:
114             newclass = store.make_class(self.ResultName)
115             store.register(newclass)
116             return newclass
117
118
119 View.one_to_many('ID', Snapshot, 'ViewID')
120
121
122 def register_classes(store):
123     store.register(View)
124     store.register(Snapshot)
125
Note: See TracBrowser for help on using the browser.