aboutsummaryrefslogtreecommitdiffstats
path: root/util/persisted_lamport.go
diff options
context:
space:
mode:
authorMichael Muré <batolettre@gmail.com>2018-08-05 15:27:46 +0200
committerMichael Muré <batolettre@gmail.com>2018-08-05 15:27:46 +0200
commitb2f20c9a61715b0a60f9e55688dbed221d775c7e (patch)
tree827d9a62a86cdd10061cb5f0289935c158f54191 /util/persisted_lamport.go
parent90fb85e067326b0f0a121e781f87df762f385592 (diff)
downloadgit-bug-b2f20c9a61715b0a60f9e55688dbed221d775c7e.tar.gz
util: add a Lamport clock implementation as well as a persistable one
Diffstat (limited to 'util/persisted_lamport.go')
-rw-r--r--util/persisted_lamport.go81
1 files changed, 81 insertions, 0 deletions
diff --git a/util/persisted_lamport.go b/util/persisted_lamport.go
new file mode 100644
index 00000000..43a2863c
--- /dev/null
+++ b/util/persisted_lamport.go
@@ -0,0 +1,81 @@
+package util
+
+import (
+ "fmt"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+)
+
+type PersistedLamport struct {
+ LamportClock
+ filePath string
+}
+
+func NewPersistedLamport(filePath string) *PersistedLamport {
+ clock := &PersistedLamport{
+ filePath: filePath,
+ }
+ return clock
+}
+
+func LoadPersistedLamport(filePath string) (*PersistedLamport, error) {
+ clock := &PersistedLamport{
+ filePath: filePath,
+ }
+
+ err := clock.read()
+ if err != nil {
+ return nil, err
+ }
+
+ return clock, nil
+}
+
+func (c *PersistedLamport) Witness(time LamportTime) error {
+ c.LamportClock.Witness(time)
+ return c.Write()
+}
+
+func (c *PersistedLamport) Time() LamportTime {
+ // Equivalent to:
+ //
+ // res = c.LamportClock.Time()
+ // bugClock.Increment()
+ //
+ // ... but thread safe
+ return c.Increment() - 1
+}
+
+func (c *PersistedLamport) read() error {
+ content, err := ioutil.ReadFile(c.filePath)
+ if err != nil {
+ return err
+ }
+
+ var value uint64
+ n, err := fmt.Sscanf(string(content), "%d", &value)
+
+ if err != nil {
+ return err
+ }
+
+ if n != 1 {
+ return fmt.Errorf("could not read the clock")
+ }
+
+ c.LamportClock = NewLamportClockWithTime(value)
+
+ return nil
+}
+
+func (c *PersistedLamport) Write() error {
+ dir := filepath.Dir(c.filePath)
+ err := os.MkdirAll(dir, 0777)
+ if err != nil {
+ return err
+ }
+
+ data := []byte(fmt.Sprintf("%d", c.LamportClock.Time()))
+ return ioutil.WriteFile(c.filePath, data, 0644)
+}