import repository from arizona
[raven.git] / apps / gacks / gackscalendar.py
1 import fcntl
2 import os
3
4 from gacksexcep import *
5 from gackshandle import *
6
7 class GacksCalendar:
8     def __init__(self):
9         self.lockf = None
10         self.lockfname = "/tmp/gackscalendar.lock"
11
12     def query_overlap(self, id=None, unitStart=0, unitStop=INFINITY, timeStart=0, timeStop=INFINITY, hasAllocator=None, isAllocator=None):
13         raise "query_overlap not defined"
14
15     def query_exact(self, id=None, unitStart=0, unitStop=INFINITY, timeStart=0, timeStop=INFINITY, hasAllocator=None, isAllocator=None):
16         raise "query_exact not defined"
17
18     def reset(self):
19         pass
20
21     def insert_record(self, item):
22         pass
23
24     def is_empty(self):
25         return True
26
27     def lock(self):
28         assert(self.lockf == None)
29         self.lockf = open(self.lockfname, "w")\r
30         fcntl.flock(self.lockf, fcntl.LOCK_EX)\r
31 \r
32     def unlock(self):
33         assert(self.lockf != None)
34         fcntl.flock(self.lockf, fcntl.LOCK_UN)
35         self.lockf.close()
36         # XXX is there a race here?
37         if os.path.isfile(self.lockfname):
38             os.unlink(self.lockfname)
39         self.lockf = None
40
41     def save(self):
42         pass
43
44     def open(self):
45         pass
46
47     def close(self):
48         self.save()
49
50     def query_handles_overlap(self, handles):
51         results = []
52         for handle in handles:
53             items = self.query_overlap(handle.id, handle.unitStart, handle.unitStop, handle.timeStart, handle.timeStop)
54             for item in items:
55                 if not item.is_in_list(results):
56                     results.append(item)
57         return results
58
59     def query_handles_exact(self, handles):
60         results = []
61         for handle in handles:
62             items = self.query_exact(handle.id, handle.unitStart, handle.unitStop, handle.timeStart, handle.timeStop)
63             for item in items:
64                 if not item.is_in_list(results):
65                     results.append(item)
66         return results
67
68     def defragment_pass(self, minTime=None):
69         """ returns a list that describes the items absorbed. empty list of
70             nothing absorbed.
71         """
72
73         items = self.query_overlap()
74
75         delete_set = []
76         absorb_list = []
77
78         i=0;
79         while (i<len(items)):
80             item = items[i]
81             new_item = item.clone()
82
83             j = i + 1
84             while (j<len(items)):
85                 candidate = items[j];
86
87                 # Check to see if new_item can absorb the candidate. If it
88                 # can, then we
89                 if new_item.try_absorb(candidate, minTime):
90                     if (delete_set == []):
91                         delete_set = [item]
92                     delete_set.append(candidate)
93                     absorb_list.append(item.as_string() + "<" + candidate.as_string())
94
95                 j = j + 1
96
97             # If we were able to absorb some items, then delete all of the
98             # original records, and add new_item to the calendar.
99             if (delete_set != []):
100                 for remove_item in delete_set:
101                     file("/tmp/log","a").write("remove:"+remove_item.as_string()+"\n")
102                     self.remove_record(remove_item)
103                 file("/tmp/log","a").write("insert:"+new_item.as_string()+"\n")
104                 self.insert_record(new_item)
105                 return absorb_list
106
107             i = i +1
108
109         return absorb_list
110
111     def defragment(self, minTime=None):
112         """ returns a list that describes the items absorbed. empty list of
113             nothing absorbed.
114         """
115
116         total = 0;
117         absorb_list = []
118
119         # keep running until we have no work left to do
120         while True:
121             this_pass = self.defragment_pass(minTime)
122             if this_pass == []:
123                 break
124             absorb_list.extend(this_pass)
125
126         return absorb_list
127
128     def dict_to_item(self, dict):
129         return GacksRecord(dict = dict)
130
131     def garbage_collect(self, timeStop=None):
132         pass
133
134     def update_record(self, item):
135         self.remove_record(item)
136         self.insert_record(item)
137
138     def test_id(self, x, y):
139         if x==None:
140             return True
141         else:
142             return (x == y)
143
144     def test_equal(self, x, y):
145         if x==None:
146             return True
147         elif (x==INFINITY) or (y==INFINITY):
148             return(str(x)==str(y))
149         else:
150             return (int(x)==int(y))
151
152     def test_lesser(self, x, y):
153         if x==None:
154             return True
155         elif y==INFINITY:
156             return True
157         else:
158             return (int(x)<int(y))
159
160     def test_greater(self, x, y):
161         if x==None:
162             return True
163         elif x==INFINITY:
164             return True
165         elif y==INFINITY:
166             return False
167         else:
168             return (int(x)>int(y))
169
170     def test_allocator(self, x, list):
171         if x==None:
172             return True
173         if not list:
174             return False
175         return (x in list)
176
177     def test_last_allocator(self, x, list):
178         if x==None:
179             return True
180         if not list:
181             return False
182         return (x == list[-1])
183
184
185
186