253
|
1 import gevent |
|
2 import fcntl |
|
3 import hashlib |
|
4 |
|
5 class Settings(object): |
|
6 RAND_SIZE = 15 # 120 bits |
|
7 |
|
8 """ Handles state updates from both the web UI and from the fridge client. |
|
9 The fridge client is canonical. It provides the epoch (apart from 'startepoch'), that |
|
10 is changed any time the fridge reloads its local config. The fridge only accepts |
|
11 updates that have the same epoch. |
|
12 |
|
13 When the web UI changes it keeps the same epoch but generates a new tag. The fridge sends |
|
14 its current known tag and waits for it to change. |
|
15 |
|
16 content is opaque, presently a dictionary of decoded json |
|
17 """ |
|
18 |
|
19 def __init__(self): |
|
20 self.event = gevent.event.Event() |
|
21 self.contents = None |
|
22 self.epoch = None |
|
23 self.tag = None |
|
24 |
|
25 self.update(self, None, 'startepoch') |
|
26 |
|
27 def wait(self, epoch_tag = None, timeout = None): |
|
28 """ returns false if the timeout was hit """ |
|
29 if self.epoch_tag() != epoch_tag: |
|
30 # has alredy changed |
|
31 return True |
|
32 return self.event.wait(timeout) |
|
33 |
|
34 def epoch_tag(self): |
|
35 return '%s-%s' % (self.epoch, self.tag) |
|
36 |
|
37 def random(self): |
|
38 return binascii.hexlify(os.urandom(self.RAND_SIZE)) |
|
39 |
|
40 def update(self, contents, epoch = None): |
|
41 """ replaces settings contents and updates waiters if changed """ |
|
42 if epoch: |
|
43 if self.epoch == epoch: |
|
44 return |
|
45 else: |
|
46 self.epoch = epoch |
|
47 |
|
48 self.tag = self.random() |
|
49 self.contents = contents |
|
50 |
|
51 self.event.set() |
|
52 self.event.clear() |
|
53 |
|
54 def get(self): |
|
55 """ Returns (contents, epoch-tag) """ |
|
56 return self.contents, self.epoch_tag() |
|
57 |
|
58 |
|
59 |
|
60 |
|
61 |