// a persistent list using a clever combination of persisting and logging
// (well, only logging as of now)
// Note: don't put in static initializer (programID not set yet)
static class PersistentList extends AbstractList {
new List m;
File file;
PersistentList(S fileName) {
this(getProgramFile(fileName));
}
PersistentList(S progID, S fileName) {
this(getProgramFile(progID, fileName));
}
*(File *file) {
for (S s : scanLog(file)) pcall {
L l = cast unstructure(s);
if (eq(l.get(0), "add"))
m.put((A) l.get(1), (B) l.get(2));
else if (eq(l.get(0), "remove"))
m.remove((A) l.get(1));
else
print("Unknown command in log: " + l.get(0));
}
}
// just delegates
public int size() {
ret m.size();
}
public B get(int i) {
ret m.get(i);
}
// TODO: calling remove() in the iterator will have unpersisted
// effects.
public Set> entrySet() {
ret m.entrySet();
}
// delegates with logging
public B put(A a, B b) {
B result = m.put(a, b);
logQuoted(file, structure(litlist("add", a, b)));
ret result;
}
public B remove(O a) {
B result = m.remove(a);
logQuoted(file, structure(litlist("remove", a)));
ret result;
}
}