File: store.go

package info (click to toggle)
golang-github-canonical-go-dqlite 2.0.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, trixie
  • size: 720 kB
  • sloc: sh: 380; makefile: 5
file content (92 lines) | stat: -rw-r--r-- 1,986 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
package client

import (
	"context"
	"io/ioutil"
	"os"
	"sync"

	"github.com/google/renameio"
	"gopkg.in/yaml.v2"

	"github.com/canonical/go-dqlite/v2/internal/protocol"
)

// NodeStore is used by a dqlite client to get an initial list of candidate
// dqlite nodes that it can dial in order to find a leader dqlite node to use.
type NodeStore = protocol.NodeStore

// NodeRole identifies the role of a node.
type NodeRole = protocol.NodeRole

// NodeInfo holds information about a single server.
type NodeInfo = protocol.NodeInfo

// InmemNodeStore keeps the list of target dqlite nodes in memory.
type InmemNodeStore = protocol.InmemNodeStore

// NewInmemNodeStore creates NodeStore which stores its data in-memory.
var NewInmemNodeStore = protocol.NewInmemNodeStore

// Persists a list addresses of dqlite nodes in a YAML file.
type YamlNodeStore struct {
	path    string
	servers []NodeInfo
	mu      sync.RWMutex
}

// NewYamlNodeStore creates a new YamlNodeStore backed by the given YAML file.
func NewYamlNodeStore(path string) (*YamlNodeStore, error) {
	servers := []NodeInfo{}

	_, err := os.Stat(path)
	if err != nil {
		if !os.IsNotExist(err) {
			return nil, err
		}
	} else {
		data, err := ioutil.ReadFile(path)
		if err != nil {
			return nil, err
		}

		if err := yaml.Unmarshal(data, &servers); err != nil {
			return nil, err
		}
	}

	store := &YamlNodeStore{
		path:    path,
		servers: servers,
	}

	return store, nil
}

// Get the current servers.
func (s *YamlNodeStore) Get(ctx context.Context) ([]NodeInfo, error) {
	s.mu.RLock()
	defer s.mu.RUnlock()
	ret := make([]NodeInfo, len(s.servers))
	copy(ret, s.servers)
	return ret, nil
}

// Set the servers addresses.
func (s *YamlNodeStore) Set(ctx context.Context, servers []NodeInfo) error {
	s.mu.Lock()
	defer s.mu.Unlock()

	data, err := yaml.Marshal(servers)
	if err != nil {
		return err
	}

	if err := renameio.WriteFile(s.path, data, 0600); err != nil {
		return err
	}

	s.servers = servers

	return nil
}