forked from M-Labs/artiq
sync_struct: support nested structures
This commit is contained in:
parent
893c18679f
commit
f12e721974
|
@ -14,10 +14,10 @@ class FlatFileDB:
|
||||||
self.hooks = []
|
self.hooks = []
|
||||||
|
|
||||||
def save(self):
|
def save(self):
|
||||||
pyon.store_file(self.filename, self.data.backing_struct)
|
pyon.store_file(self.filename, self.data.read)
|
||||||
|
|
||||||
def request(self, name):
|
def request(self, name):
|
||||||
return self.data.backing_struct[name]
|
return self.data.read[name]
|
||||||
|
|
||||||
def set(self, name, value):
|
def set(self, name, value):
|
||||||
self.data[name] = value
|
self.data[name] = value
|
||||||
|
@ -40,12 +40,12 @@ class SimpleHistory:
|
||||||
self.history = Notifier([])
|
self.history = Notifier([])
|
||||||
|
|
||||||
def set(self, timestamp, name, value):
|
def set(self, timestamp, name, value):
|
||||||
if len(self.history.backing_struct) >= self.depth:
|
if len(self.history.read) >= self.depth:
|
||||||
del self.history[0]
|
del self.history[0]
|
||||||
self.history.append((timestamp, name, value))
|
self.history.append((timestamp, name, value))
|
||||||
|
|
||||||
def delete(self, timestamp, name):
|
def delete(self, timestamp, name):
|
||||||
if len(self.history.backing_struct) >= self.depth:
|
if len(self.history.read) >= self.depth:
|
||||||
del self.history[0]
|
del self.history[0]
|
||||||
self.history.append((timestamp, name))
|
self.history.append((timestamp, name))
|
||||||
|
|
||||||
|
|
|
@ -20,8 +20,8 @@ class Scheduler:
|
||||||
return r
|
return r
|
||||||
|
|
||||||
def new_prid(self):
|
def new_prid(self):
|
||||||
prids = set(range(len(self.periodic.backing_struct) + 1))
|
prids = set(range(len(self.periodic.read) + 1))
|
||||||
prids -= set(self.periodic.backing_struct.keys())
|
prids -= set(self.periodic.read.keys())
|
||||||
return next(iter(prids))
|
return next(iter(prids))
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
|
@ -44,7 +44,7 @@ class Scheduler:
|
||||||
|
|
||||||
def cancel_once(self, rid):
|
def cancel_once(self, rid):
|
||||||
idx = next(idx for idx, (qrid, _, _)
|
idx = next(idx for idx, (qrid, _, _)
|
||||||
in enumerate(self.queue.backing_struct)
|
in enumerate(self.queue.read)
|
||||||
if qrid == rid)
|
if qrid == rid)
|
||||||
if idx == 0:
|
if idx == 0:
|
||||||
# Cannot cancel when already running
|
# Cannot cancel when already running
|
||||||
|
@ -75,7 +75,7 @@ class Scheduler:
|
||||||
while True:
|
while True:
|
||||||
min_next_run = None
|
min_next_run = None
|
||||||
min_prid = None
|
min_prid = None
|
||||||
for prid, params in self.periodic.backing_struct.items():
|
for prid, params in self.periodic.read.items():
|
||||||
if min_next_run is None or params[0] < min_next_run:
|
if min_next_run is None or params[0] < min_next_run:
|
||||||
min_next_run = params[0]
|
min_next_run = params[0]
|
||||||
min_prid = prid
|
min_prid = prid
|
||||||
|
@ -89,7 +89,7 @@ class Scheduler:
|
||||||
return min_next_run
|
return min_next_run
|
||||||
|
|
||||||
next_run, run_params, timeout, period = \
|
next_run, run_params, timeout, period = \
|
||||||
self.periodic.backing_struct[min_prid]
|
self.periodic.read[min_prid]
|
||||||
self.periodic[min_prid] = now + period, run_params, timeout, period
|
self.periodic[min_prid] = now + period, run_params, timeout, period
|
||||||
|
|
||||||
rid = self.new_rid()
|
rid = self.new_rid()
|
||||||
|
@ -101,8 +101,8 @@ class Scheduler:
|
||||||
def _schedule(self):
|
def _schedule(self):
|
||||||
while True:
|
while True:
|
||||||
next_periodic = yield from self._run_periodic()
|
next_periodic = yield from self._run_periodic()
|
||||||
if self.queue.backing_struct:
|
if self.queue.read:
|
||||||
rid, run_params, timeout = self.queue.backing_struct[0]
|
rid, run_params, timeout = self.queue.read[0]
|
||||||
yield from self._run(rid, run_params, timeout)
|
yield from self._run(rid, run_params, timeout)
|
||||||
del self.queue[0]
|
del self.queue[0]
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import asyncio
|
import asyncio
|
||||||
|
from operator import getitem
|
||||||
|
|
||||||
from artiq.management import pyon
|
from artiq.management import pyon
|
||||||
from artiq.management.tools import AsyncioServer
|
from artiq.management.tools import AsyncioServer
|
||||||
|
@ -52,56 +53,74 @@ class Subscriber:
|
||||||
|
|
||||||
if action == "init":
|
if action == "init":
|
||||||
target = self.target_builder(obj["struct"])
|
target = self.target_builder(obj["struct"])
|
||||||
elif action == "append":
|
else:
|
||||||
target.append(obj["x"])
|
for key in obj["path"]:
|
||||||
elif action == "insert":
|
target = getitem(target, key)
|
||||||
target.insert(obj["i"], obj["x"])
|
if action == "append":
|
||||||
elif action == "pop":
|
target.append(obj["x"])
|
||||||
target.pop(obj["i"])
|
elif action == "insert":
|
||||||
elif action == "setitem":
|
target.insert(obj["i"], obj["x"])
|
||||||
target.__setitem__(obj["key"], obj["value"])
|
elif action == "pop":
|
||||||
elif action == "delitem":
|
target.pop(obj["i"])
|
||||||
target.__delitem__(obj["key"])
|
elif action == "setitem":
|
||||||
|
target.__setitem__(obj["key"], obj["value"])
|
||||||
|
elif action == "delitem":
|
||||||
|
target.__delitem__(obj["key"])
|
||||||
|
|
||||||
if self.notify_cb is not None:
|
if self.notify_cb is not None:
|
||||||
self.notify_cb()
|
self.notify_cb()
|
||||||
|
|
||||||
|
|
||||||
class Notifier:
|
class Notifier:
|
||||||
def __init__(self, backing_struct):
|
def __init__(self, backing_struct, publisher=None, path=[]):
|
||||||
self.backing_struct = backing_struct
|
self.read = backing_struct
|
||||||
self.publisher = None
|
self.publisher = publisher
|
||||||
|
self._backing_struct = backing_struct
|
||||||
|
self._path = path
|
||||||
|
|
||||||
# Backing struct modification methods.
|
# Backing struct modification methods.
|
||||||
# All modifications must go through them!
|
# All modifications must go through them!
|
||||||
|
|
||||||
def append(self, x):
|
def append(self, x):
|
||||||
self.backing_struct.append(x)
|
self._backing_struct.append(x)
|
||||||
if self.publisher is not None:
|
if self.publisher is not None:
|
||||||
self.publisher.publish(self, {"action": "append", "x": x})
|
self.publisher.publish(self, {"action": "append",
|
||||||
|
"path": self._path,
|
||||||
|
"x": x})
|
||||||
|
|
||||||
def insert(self, i, x):
|
def insert(self, i, x):
|
||||||
self.backing_struct.insert(i, x)
|
self._backing_struct.insert(i, x)
|
||||||
if self.publisher is not None:
|
if self.publisher is not None:
|
||||||
self.publisher.publish(self, {"action": "insert", "i": i, "x": x})
|
self.publisher.publish(self, {"action": "insert",
|
||||||
|
"path": self._path,
|
||||||
|
"i": i, "x": x})
|
||||||
|
|
||||||
def pop(self, i=-1):
|
def pop(self, i=-1):
|
||||||
r = self.backing_struct.pop(i)
|
r = self._backing_struct.pop(i)
|
||||||
if self.publisher is not None:
|
if self.publisher is not None:
|
||||||
self.publisher.publish(self, {"action": "pop", "i": i})
|
self.publisher.publish(self, {"action": "pop",
|
||||||
|
"path": self._path,
|
||||||
|
"i": i})
|
||||||
return r
|
return r
|
||||||
|
|
||||||
def __setitem__(self, key, value):
|
def __setitem__(self, key, value):
|
||||||
self.backing_struct.__setitem__(key, value)
|
self._backing_struct.__setitem__(key, value)
|
||||||
if self.publisher is not None:
|
if self.publisher is not None:
|
||||||
self.publisher.publish(self, {"action": "setitem",
|
self.publisher.publish(self, {"action": "setitem",
|
||||||
|
"path": self._path,
|
||||||
"key": key,
|
"key": key,
|
||||||
"value": value})
|
"value": value})
|
||||||
|
|
||||||
def __delitem__(self, key):
|
def __delitem__(self, key):
|
||||||
self.backing_struct.__delitem__(key)
|
self._backing_struct.__delitem__(key)
|
||||||
if self.publisher is not None:
|
if self.publisher is not None:
|
||||||
self.publisher.publish(self, {"action": "delitem", "key": key})
|
self.publisher.publish(self, {"action": "delitem",
|
||||||
|
"path": self._path,
|
||||||
|
"key": key})
|
||||||
|
|
||||||
|
def __getitem__(self, key):
|
||||||
|
item = getitem(self._backing_struct, key)
|
||||||
|
return Notifier(item, self.publisher, self._path + [key])
|
||||||
|
|
||||||
|
|
||||||
class Publisher(AsyncioServer):
|
class Publisher(AsyncioServer):
|
||||||
|
@ -131,7 +150,7 @@ class Publisher(AsyncioServer):
|
||||||
except KeyError:
|
except KeyError:
|
||||||
return
|
return
|
||||||
|
|
||||||
obj = {"action": "init", "struct": notifier.backing_struct}
|
obj = {"action": "init", "struct": notifier.read}
|
||||||
line = pyon.encode(obj) + "\n"
|
line = pyon.encode(obj) + "\n"
|
||||||
writer.write(line.encode())
|
writer.write(line.encode())
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue