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