1package lamport
2
3import (
4 "fmt"
5 "io/ioutil"
6 "os"
7 "path/filepath"
8)
9
10type Persisted struct {
11 Clock
12 filePath string
13}
14
15func NewPersisted(filePath string) (*Persisted, error) {
16 clock := &Persisted{
17 Clock: NewClock(),
18 filePath: filePath,
19 }
20
21 dir := filepath.Dir(filePath)
22 err := os.MkdirAll(dir, 0777)
23 if err != nil {
24 return nil, err
25 }
26
27 return clock, nil
28}
29
30func LoadPersisted(filePath string) (*Persisted, error) {
31 clock := &Persisted{
32 filePath: filePath,
33 }
34
35 err := clock.read()
36 if err != nil {
37 return nil, err
38 }
39
40 return clock, nil
41}
42
43func (c *Persisted) Increment() (Time, error) {
44 time := c.Clock.Increment()
45 return time, c.Write()
46}
47
48func (c *Persisted) Witness(time Time) error {
49 // TODO: rework so that we write only when the clock was actually updated
50 c.Clock.Witness(time)
51 return c.Write()
52}
53
54func (c *Persisted) read() error {
55 content, err := ioutil.ReadFile(c.filePath)
56 if err != nil {
57 return err
58 }
59
60 var value uint64
61 n, err := fmt.Sscanf(string(content), "%d", &value)
62
63 if err != nil {
64 return err
65 }
66
67 if n != 1 {
68 return fmt.Errorf("could not read the clock")
69 }
70
71 c.Clock = NewClockWithTime(value)
72
73 return nil
74}
75
76func (c *Persisted) Write() error {
77 data := []byte(fmt.Sprintf("%d", c.counter))
78 return ioutil.WriteFile(c.filePath, data, 0644)
79}