1package util
2
3import (
4 "fmt"
5 "io/ioutil"
6 "os"
7 "path/filepath"
8)
9
10type PersistedLamport struct {
11 LamportClock
12 filePath string
13}
14
15func NewPersistedLamport(filePath string) *PersistedLamport {
16 clock := &PersistedLamport{
17 LamportClock: NewLamportClock(),
18 filePath: filePath,
19 }
20 return clock
21}
22
23func LoadPersistedLamport(filePath string) (*PersistedLamport, error) {
24 clock := &PersistedLamport{
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 *PersistedLamport) Increment() (LamportTime, error) {
37 time := c.LamportClock.Increment()
38 return time, c.Write()
39}
40
41func (c *PersistedLamport) Witness(time LamportTime) error {
42 // TODO: rework so that we write only when the clock was actually updated
43 c.LamportClock.Witness(time)
44 return c.Write()
45}
46
47func (c *PersistedLamport) 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.LamportClock = NewLamportClockWithTime(value)
65
66 return nil
67}
68
69func (c *PersistedLamport) 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}