Rewrote threaded log code to be more idiomatic.
[invirt/third/libt4.git] / log.cc
1 #include "log.h"
2 #include "paxos.h"
3
4 // Paxos must maintain some durable state (i.e., that survives power
5 // failures) to run Paxos correct.  This module implements a log with
6 // all durable state to run Paxos.  Since the values chosen correspond
7 // to views, the log contains all views since the beginning of time.
8
9 log::log(proposer_acceptor *_acc, string _me) : pxs (_acc) {
10     name = "paxos-" + _me + ".log";
11     logread();
12 }
13
14 void log::logread(void) {
15     ifstream from(name);
16     string type;
17     unsigned instance;
18
19     LOG << "logread";
20     while (from >> type) {
21         if (type == "done") {
22             string v;
23             from >> instance;
24             from.get();
25             getline(from, v);
26             pxs->values[instance] = v;
27             pxs->instance_h = instance;
28             LOG << "logread: instance: " << instance << " w. v = "
29                 << pxs->values[instance];
30             pxs->accepted_value.clear();
31             pxs->promise.n = 0;
32             pxs->accepted.n = 0;
33         } else if (type == "propseen") {
34             from >> pxs->promise.n >> pxs->promise.m;
35             LOG << "logread: high update: " << pxs->promise.n << "(" << pxs->promise.m << ")";
36         } else if (type == "accepted") {
37             string v;
38             from >> pxs->accepted.n >> pxs->accepted.m;
39             from.get();
40             getline(from, v);
41             pxs->accepted_value = v;
42             LOG << "logread: prop update " << pxs->accepted.n << "(" << pxs->accepted.m << ") with v = " << pxs->accepted_value;
43         } else {
44             LOG << "logread: unknown log record";
45             VERIFY(0);
46         }
47     } 
48     from.close();
49 }
50
51 string log::dump() {
52     ifstream from(name);
53     string res;
54     string v;
55     while (getline(from, v))
56         res += v + "\n";
57     from.close();
58     return res;
59 }
60
61 void log::restore(string s) {
62     LOG << "restore: " << s;
63     ofstream f(name, ios::trunc);
64     f << s;
65     f.close();
66 }
67
68 // XXX should be an atomic operation
69 void log::loginstance(unsigned instance, string v) {
70     ofstream f(name, ios::app);
71     f << "done " << instance << " " << v << "\n";
72     f.close();
73 }
74
75 // an acceptor should call logprop(promise) when it
76 // receives a prepare to which it responds prepare_ok().
77 void log::logprop(prop_t promise) {
78     ofstream f(name, ios::app);
79     f << "propseen " << promise.n << " " << promise.m << "\n";
80     f.close();
81 }
82
83 // an acceptor should call logaccept(accepted, accepted_value) when it
84 // receives an accept RPC to which it replies accept_ok().
85 void log::logaccept(prop_t n, string v) {
86     ofstream f(name, ios::app);
87     f << "accepted " << n.n << " " << n.m << " " << v << "\n";
88     f.close();
89 }