persisted_lamport.go

 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}