persisted_lamport.go

 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		filePath: filePath,
18	}
19	return clock
20}
21
22func LoadPersistedLamport(filePath string) (*PersistedLamport, error) {
23	clock := &PersistedLamport{
24		filePath: filePath,
25	}
26
27	err := clock.read()
28	if err != nil {
29		return nil, err
30	}
31
32	return clock, nil
33}
34
35func (c *PersistedLamport) Witness(time LamportTime) error {
36	c.LamportClock.Witness(time)
37	return c.Write()
38}
39
40func (c *PersistedLamport) Time() LamportTime {
41	// Equivalent to:
42	//
43	// res = c.LamportClock.Time()
44	// bugClock.Increment()
45	//
46	// ... but thread safe
47	return c.Increment() - 1
48}
49
50func (c *PersistedLamport) read() error {
51	content, err := ioutil.ReadFile(c.filePath)
52	if err != nil {
53		return err
54	}
55
56	var value uint64
57	n, err := fmt.Sscanf(string(content), "%d", &value)
58
59	if err != nil {
60		return err
61	}
62
63	if n != 1 {
64		return fmt.Errorf("could not read the clock")
65	}
66
67	c.LamportClock = NewLamportClockWithTime(value)
68
69	return nil
70}
71
72func (c *PersistedLamport) Write() error {
73	dir := filepath.Dir(c.filePath)
74	err := os.MkdirAll(dir, 0777)
75	if err != nil {
76		return err
77	}
78
79	data := []byte(fmt.Sprintf("%d", c.LamportClock.Time()))
80	return ioutil.WriteFile(c.filePath, data, 0644)
81}