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 {
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}