Comments (5)
Hi @ardhipoetra, thanks for your question. I haven't really tried compiling with gccgo
yet, I don't know if it's compiles this way. I would be happy to accept a PR that fixes any issues our project has with gccgo
though.
from go-dqlite.
@ardhipoetra do you want to take a stab at this? Otherwise I'll probably close this issue for now.
from go-dqlite.
Right now I don't have proper fix nor the time to tackle this. It looks like the problem is somewhere on the bindings with the dqlite lib. Removing all the bindings (since in my case, I don't need them), is a dirty-but-working fix.
Reference : commit c6c3f4078dad56a90f6b29f9e9796828935ed9f8 in my fork.
from go-dqlite.
Okay, I think the problem is caused by the alias declarations (introduced in Go 1.9).
I can successfully build if I:
- Comment-out all alias declarations (breaking change).
- Fix the errors caused by this (also a breaking change).
- Change
Dockerfile
to useFROM golang:1.19.5-alpine3.17
.
I still cannot build with the original FROM golang:1.14-alpine
, but at least the error is different now.
I'm not familiar enough with go-dqlite
or gccgo
to confidently say this is the actual cause of the issue, or its fix. And I didn't even try the compiled program, I just stopped after the go build
command succeeded.
But I hope this helps in some way.
This is the Dockerfile
I'm using, slighly modified from @ardhipoetra's:
Dockerfile
FROM golang:1.19.5-alpine3.17
# This doesn't build, but the error is different.
#FROM golang:1.14-alpine
WORKDIR /
RUN apk add --no-cache --update gcc-go ca-certificates git dumb-init automake libtool autoconf libuv-dev lz4-dev make gcc musl-dev linux-headers
#### raft and dqlite ####
RUN git clone https://github.com/canonical/raft
WORKDIR /raft
RUN autoreconf -i && ./configure --enable-uv --prefix=/usr && make -j4 install
WORKDIR /
RUN apk add sqlite-dev
RUN git clone https://github.com/canonical/dqlite
WORKDIR /dqlite
RUN autoreconf -i && ./configure --prefix=/usr && make -j4 install
WORKDIR /
RUN git clone https://github.com/canonical/go-dqlite
WORKDIR /go-dqlite
# At the moment of writing this Dockerfile, this was
# the most recent commit on `master`.
#RUN git checkout 78005e6970d56e985e46eac2b371cdc95af3d591
# This `diff.txt` is in the GitHub comment.
COPY ./diff.txt ./diff.txt
RUN git apply diff.txt
ENV CGO_LDFLAGS_ALLOW="-Wl,-z,now"
RUN go build -v -tags libsqlite3 -compiler gccgo -buildmode=exe -gccgoflags -g ./cmd/dqlite-demo
The diff.txt
mentioned in the Dockerfile
(these are breaking changes):
diff.txt
diff --git a/app/app.go b/app/app.go
index dbee296..1a621df 100644
--- a/app/app.go
+++ b/app/app.go
@@ -15,6 +15,7 @@ import (
"github.com/canonical/go-dqlite/client"
"github.com/canonical/go-dqlite/driver"
"github.com/canonical/go-dqlite/internal/protocol"
+ "github.com/canonical/go-dqlite/logging"
"github.com/pkg/errors"
"golang.org/x/sync/semaphore"
)
@@ -32,11 +33,11 @@ type App struct {
nodeBindAddress string
listener net.Listener
tls *tlsSetup
- dialFunc client.DialFunc
- store client.NodeStore
+ dialFunc protocol.DialFunc
+ store protocol.NodeStore
driver *driver.Driver
driverName string
- log client.LogFunc
+ log logging.Func
ctx context.Context
stop context.CancelFunc // Signal App.run() to stop.
proxyCh chan struct{} // Waits for App.proxy() to return.
@@ -78,7 +79,7 @@ func New(dir string, options ...Option) (app *App, err error) {
}()
// Load our ID, or generate one if we are joining.
- info := client.NodeInfo{}
+ info := protocol.NodeInfo{}
infoFileExists, err := fileExists(dir, infoFile)
if err != nil {
return nil, err
@@ -142,15 +143,15 @@ func New(dir string, options ...Option) (app *App, err error) {
// If this is a brand new application node, populate the store
// either with the node's address (for bootstrap nodes) or with
// the given cluster addresses (for joining nodes).
- nodes := []client.NodeInfo{}
+ nodes := []protocol.NodeInfo{}
if info.ID == dqlite.BootstrapID {
- nodes = append(nodes, client.NodeInfo{Address: info.Address})
+ nodes = append(nodes, protocol.NodeInfo{Address: info.Address})
} else {
if len(o.Cluster) == 0 {
return nil, fmt.Errorf("no cluster addresses provided")
}
for _, address := range o.Cluster {
- nodes = append(nodes, client.NodeInfo{Address: address})
+ nodes = append(nodes, protocol.NodeInfo{Address: address})
}
}
if err := store.Set(context.Background(), nodes); err != nil {
@@ -161,7 +162,7 @@ func New(dir string, options ...Option) (app *App, err error) {
// Start the local dqlite engine.
ctx, stop := context.WithCancel(context.Background())
- var nodeDial client.DialFunc
+ var nodeDial protocol.DialFunc
if o.Conn != nil {
nodeDial = extDialFuncWithProxy(ctx, o.Conn.dialFunc)
} else if o.TLS != nil {
@@ -514,7 +515,7 @@ func (a *App) run(ctx context.Context, frequency time.Duration, join bool) {
// Attempt to join the cluster if this is a brand new node.
if join {
- info := client.NodeInfo{ID: a.id, Address: a.address, Role: client.Spare}
+ info := protocol.NodeInfo{ID: a.id, Address: a.address, Role: client.Spare}
if err := cli.Add(ctx, info); err != nil {
a.warn("join cluster: %v", err)
delay = time.Second
@@ -568,7 +569,7 @@ func (a *App) run(ctx context.Context, frequency time.Duration, join bool) {
}
// Possibly change our own role at startup.
-func (a *App) maybePromoteOurselves(ctx context.Context, cli *client.Client, nodes []client.NodeInfo) error {
+func (a *App) maybePromoteOurselves(ctx context.Context, cli *client.Client, nodes []protocol.NodeInfo) error {
roles := a.makeRolesChanges(nodes)
role := roles.Assume(a.id)
@@ -641,8 +642,8 @@ again:
// Probe all given nodes for connectivity and metadata, then return a
// RolesChanges object.
-func (a *App) makeRolesChanges(nodes []client.NodeInfo) RolesChanges {
- state := map[client.NodeInfo]*client.NodeMetadata{}
+func (a *App) makeRolesChanges(nodes []protocol.NodeInfo) RolesChanges {
+ state := map[protocol.NodeInfo]*client.NodeMetadata{}
for _, node := range nodes {
state[node] = nil
}
diff --git a/app/dial.go b/app/dial.go
index 96d536f..0375fda 100644
--- a/app/dial.go
+++ b/app/dial.go
@@ -6,12 +6,12 @@ import (
"fmt"
"net"
- "github.com/canonical/go-dqlite/client"
+ "github.com/canonical/go-dqlite/internal/protocol"
)
// Like client.DialFuncWithTLS but also starts the proxy, since the raft
// connect function only supports Unix and TCP connections.
-func makeNodeDialFunc(appCtx context.Context, config *tls.Config) client.DialFunc {
+func makeNodeDialFunc(appCtx context.Context, config *tls.Config) protocol.DialFunc {
dial := func(ctx context.Context, addr string) (net.Conn, error) {
clonedConfig := config.Clone()
if len(clonedConfig.ServerName) == 0 {
@@ -42,7 +42,7 @@ func makeNodeDialFunc(appCtx context.Context, config *tls.Config) client.DialFun
// extDialFuncWithProxy executes given DialFunc and then copies the data back
// and forth between the remote connection and a local unix socket.
-func extDialFuncWithProxy(appCtx context.Context, dialFunc client.DialFunc) client.DialFunc {
+func extDialFuncWithProxy(appCtx context.Context, dialFunc protocol.DialFunc) protocol.DialFunc {
return func(ctx context.Context, addr string) (net.Conn, error) {
goUnix, cUnix, err := socketpair()
if err != nil {
diff --git a/app/options.go b/app/options.go
index d0b0520..1e795ff 100644
--- a/app/options.go
+++ b/app/options.go
@@ -8,8 +8,10 @@ import (
"strings"
"time"
- "github.com/canonical/go-dqlite"
"github.com/canonical/go-dqlite/client"
+ "github.com/canonical/go-dqlite/internal/bindings"
+ "github.com/canonical/go-dqlite/internal/protocol"
+ "github.com/canonical/go-dqlite/logging"
)
// Option can be used to tweak app parameters.
@@ -49,7 +51,7 @@ func WithCluster(cluster []string) Option {
// whenever dqlite needs to make an outside connection.
//
// Also takes a net.Conn channel that should be received when the external connection has been accepted.
-func WithExternalConn(dialFunc client.DialFunc, acceptCh chan net.Conn) Option {
+func WithExternalConn(dialFunc protocol.DialFunc, acceptCh chan net.Conn) Option {
return func(options *options) {
options.Conn = &connSetup{
dialFunc: dialFunc,
@@ -140,7 +142,7 @@ func WithRolesAdjustmentFrequency(frequency time.Duration) Option {
}
// WithLogFunc sets a custom log function.
-func WithLogFunc(log client.LogFunc) Option {
+func WithLogFunc(log logging.Func) Option {
return func(options *options) {
options.Log = log
}
@@ -164,7 +166,7 @@ func WithNetworkLatency(latency time.Duration) Option {
}
// WithSnapshotParams sets the raft snapshot parameters.
-func WithSnapshotParams(params dqlite.SnapshotParams) Option {
+func WithSnapshotParams(params bindings.SnapshotParams) Option {
return func(options *options) {
options.SnapshotParams = params
}
@@ -187,14 +189,14 @@ type tlsSetup struct {
}
type connSetup struct {
- dialFunc client.DialFunc
+ dialFunc protocol.DialFunc
acceptCh chan net.Conn
}
type options struct {
Address string
Cluster []string
- Log client.LogFunc
+ Log logging.Func
TLS *tlsSetup
Conn *connSetup
Voters int
@@ -203,7 +205,7 @@ type options struct {
FailureDomain uint64
NetworkLatency time.Duration
UnixSocket string
- SnapshotParams dqlite.SnapshotParams
+ SnapshotParams bindings.SnapshotParams
DiskMode bool
}
@@ -272,7 +274,7 @@ func defaultAddress() (addr string, err error) {
return "", fmt.Errorf("no suitable net.Interface found: %v", err)
}
-func defaultLogFunc(l client.LogLevel, format string, a ...interface{}) {
+func defaultLogFunc(l logging.Level, format string, a ...interface{}) {
// Log only error messages
if l != client.LogError {
return
diff --git a/app/roles.go b/app/roles.go
index 5b24bdf..1fd8ba6 100644
--- a/app/roles.go
+++ b/app/roles.go
@@ -4,6 +4,7 @@ import (
"sort"
"github.com/canonical/go-dqlite/client"
+ "github.com/canonical/go-dqlite/internal/protocol"
)
const minVoters = 3
@@ -29,7 +30,7 @@ type RolesChanges struct {
// present as a key in the map, and its value should be its associated
// failure domain and weight metadata or nil if the node is currently
// offline.
- State map[client.NodeInfo]*client.NodeMetadata
+ State map[protocol.NodeInfo]*client.NodeMetadata
}
// Assume decides if a node should assume a different role than the one it
@@ -38,7 +39,7 @@ type RolesChanges struct {
// role in case there's a shortage of them.
//
// Return -1 in case no role change is needed.
-func (c *RolesChanges) Assume(id uint64) client.NodeRole {
+func (c *RolesChanges) Assume(id uint64) protocol.NodeRole {
// If the cluster is still too small, do nothing.
if c.size() < minVoters {
return -1
@@ -79,7 +80,7 @@ func (c *RolesChanges) Assume(id uint64) client.NodeRole {
//
// Return the role that should be handed over and list of candidates that
// should receive it, in order of preference.
-func (c *RolesChanges) Handover(id uint64) (client.NodeRole, []client.NodeInfo) {
+func (c *RolesChanges) Handover(id uint64) (protocol.NodeRole, []protocol.NodeInfo) {
node := c.get(id)
// If we are not in the cluster, it means we were removed, just do nothing.
@@ -126,7 +127,7 @@ func (c *RolesChanges) Handover(id uint64) (client.NodeRole, []client.NodeInfo)
//
// Return the role that should be assigned and a list of candidates that should
// assume it, in order of preference.
-func (c *RolesChanges) Adjust(leader uint64) (client.NodeRole, []client.NodeInfo) {
+func (c *RolesChanges) Adjust(leader uint64) (protocol.NodeRole, []protocol.NodeInfo) {
if c.size() == 1 {
return -1, nil
}
@@ -137,7 +138,7 @@ func (c *RolesChanges) Adjust(leader uint64) (client.NodeRole, []client.NodeInfo
if node.ID == leader || node.Role != client.Voter {
continue
}
- return client.Spare, []client.NodeInfo{node}
+ return client.Spare, []protocol.NodeInfo{node}
}
return -1, nil
}
@@ -172,7 +173,7 @@ func (c *RolesChanges) Adjust(leader uint64) (client.NodeRole, []client.NodeInfo
// If we have more online voters than desired, let's demote one of
// them.
if n := len(onlineVoters); n > c.Config.Voters {
- nodes := []client.NodeInfo{}
+ nodes := []protocol.NodeInfo{}
for _, node := range onlineVoters {
// Don't demote the leader.
if node.ID == leader {
@@ -207,7 +208,7 @@ func (c *RolesChanges) Adjust(leader uint64) (client.NodeRole, []client.NodeInfo
// If we have more online stand-bys than desired, let's demote one of
// them.
if n := len(onlineStandbys); n > c.Config.StandBys {
- nodes := []client.NodeInfo{}
+ nodes := []protocol.NodeInfo{}
for _, node := range onlineStandbys {
// Don't demote the leader.
if node.ID == leader {
@@ -234,7 +235,7 @@ func (c *RolesChanges) size() int {
// Return information about the node with the given ID, or nil if no node
// matches.
-func (c *RolesChanges) get(id uint64) *client.NodeInfo {
+func (c *RolesChanges) get(id uint64) *protocol.NodeInfo {
for node := range c.State {
if node.ID == id {
return &node
@@ -244,8 +245,8 @@ func (c *RolesChanges) get(id uint64) *client.NodeInfo {
}
// Return the online or offline nodes with the given role.
-func (c *RolesChanges) list(role client.NodeRole, online bool) []client.NodeInfo {
- nodes := []client.NodeInfo{}
+func (c *RolesChanges) list(role protocol.NodeRole, online bool) []protocol.NodeInfo {
+ nodes := []protocol.NodeInfo{}
for node, metadata := range c.State {
if node.Role == role && metadata != nil == online {
nodes = append(nodes, node)
@@ -255,13 +256,13 @@ func (c *RolesChanges) list(role client.NodeRole, online bool) []client.NodeInfo
}
// Return the number of online or offline nodes with the given role.
-func (c *RolesChanges) count(role client.NodeRole, online bool) int {
+func (c *RolesChanges) count(role protocol.NodeRole, online bool) int {
return len(c.list(role, online))
}
// Return a map of the failure domains associated with the
// given nodes.
-func (c *RolesChanges) failureDomains(nodes []client.NodeInfo) map[uint64]bool {
+func (c *RolesChanges) failureDomains(nodes []protocol.NodeInfo) map[uint64]bool {
domains := map[uint64]bool{}
for _, node := range nodes {
metadata := c.State[node]
@@ -276,7 +277,7 @@ func (c *RolesChanges) failureDomains(nodes []client.NodeInfo) map[uint64]bool {
// Sort the given candidates according to their failure domain and
// weight. Candidates belonging to a failure domain different from the given
// domains take precedence.
-func (c *RolesChanges) sortCandidates(candidates []client.NodeInfo, domains map[uint64]bool) {
+func (c *RolesChanges) sortCandidates(candidates []protocol.NodeInfo, domains map[uint64]bool) {
less := func(i, j int) bool {
metadata1 := c.metadata(candidates[i])
metadata2 := c.metadata(candidates[j])
@@ -300,6 +301,6 @@ func (c *RolesChanges) sortCandidates(candidates []client.NodeInfo, domains map[
}
// Return the metadata of the given node, if any.
-func (c *RolesChanges) metadata(node client.NodeInfo) *client.NodeMetadata {
+func (c *RolesChanges) metadata(node protocol.NodeInfo) *client.NodeMetadata {
return c.State[node]
}
diff --git a/client/client.go b/client/client.go
index c8809be..9f6ed68 100644
--- a/client/client.go
+++ b/client/client.go
@@ -4,11 +4,12 @@ import (
"context"
"github.com/canonical/go-dqlite/internal/protocol"
+ "github.com/canonical/go-dqlite/logging"
"github.com/pkg/errors"
)
// DialFunc is a function that can be used to establish a network connection.
-type DialFunc = protocol.DialFunc
+//type DialFunc = protocol.DialFunc
// Client speaks the dqlite wire protocol.
type Client struct {
@@ -19,13 +20,13 @@ type Client struct {
type Option func(*options)
type options struct {
- DialFunc DialFunc
- LogFunc LogFunc
+ DialFunc protocol.DialFunc
+ LogFunc logging.Func
}
// WithDialFunc sets a custom dial function for creating the client network
// connection.
-func WithDialFunc(dial DialFunc) Option {
+func WithDialFunc(dial protocol.DialFunc) Option {
return func(options *options) {
options.DialFunc = dial
}
@@ -33,7 +34,7 @@ func WithDialFunc(dial DialFunc) Option {
// WithLogFunc sets a custom log function.
// connection.
-func WithLogFunc(log LogFunc) Option {
+func WithLogFunc(log logging.Func) Option {
return func(options *options) {
options.LogFunc = log
}
@@ -65,7 +66,7 @@ func New(ctx context.Context, address string, options ...Option) (*Client, error
}
// Leader returns information about the current leader, if any.
-func (c *Client) Leader(ctx context.Context) (*NodeInfo, error) {
+func (c *Client) Leader(ctx context.Context) (*protocol.NodeInfo, error) {
request := protocol.Message{}
request.Init(16)
response := protocol.Message{}
@@ -82,13 +83,13 @@ func (c *Client) Leader(ctx context.Context) (*NodeInfo, error) {
return nil, errors.Wrap(err, "failed to parse Node response")
}
- info := &NodeInfo{ID: id, Address: address}
+ info := &protocol.NodeInfo{ID: id, Address: address}
return info, nil
}
// Cluster returns information about all nodes in the cluster.
-func (c *Client) Cluster(ctx context.Context) ([]NodeInfo, error) {
+func (c *Client) Cluster(ctx context.Context) ([]protocol.NodeInfo, error) {
request := protocol.Message{}
request.Init(16)
response := protocol.Message{}
@@ -154,7 +155,7 @@ func (c *Client) Dump(ctx context.Context, dbname string) ([]File, error) {
// The new node will have the role specified in node.Role. Note that if the
// desired role is Voter, the node being added must be online, since it will be
// granted voting rights only once it catches up with the leader's log.
-func (c *Client) Add(ctx context.Context, node NodeInfo) error {
+func (c *Client) Add(ctx context.Context, node protocol.NodeInfo) error {
request := protocol.Message{}
response := protocol.Message{}
@@ -190,7 +191,7 @@ func (c *Client) Add(ctx context.Context, node NodeInfo) error {
//
// If the target node does not exist or has already the desired role, an error
// is returned.
-func (c *Client) Assign(ctx context.Context, id uint64, role NodeRole) error {
+func (c *Client) Assign(ctx context.Context, id uint64, role protocol.NodeRole) error {
request := protocol.Message{}
response := protocol.Message{}
diff --git a/client/dial.go b/client/dial.go
index 5466679..88cbbe1 100644
--- a/client/dial.go
+++ b/client/dial.go
@@ -18,7 +18,7 @@ func DefaultDialFunc(ctx context.Context, address string) (net.Conn, error) {
//
// The given dial function will be used to establish the network connection,
// and the given TLS config will be used for encryption.
-func DialFuncWithTLS(dial DialFunc, config *tls.Config) DialFunc {
+func DialFuncWithTLS(dial protocol.DialFunc, config *tls.Config) protocol.DialFunc {
return func(ctx context.Context, addr string) (net.Conn, error) {
clonedConfig := config.Clone()
if len(clonedConfig.ServerName) == 0 {
diff --git a/client/leader.go b/client/leader.go
index 5de72ce..2b90946 100644
--- a/client/leader.go
+++ b/client/leader.go
@@ -12,7 +12,7 @@ import (
// each of them check if it's the current leader. If no leader is found, the
// function will keep retrying (with a capped exponential backoff) until the
// given context is canceled.
-func FindLeader(ctx context.Context, store NodeStore, options ...Option) (*Client, error) {
+func FindLeader(ctx context.Context, store protocol.NodeStore, options ...Option) (*Client, error) {
o := defaultOptions()
for _, option := range options {
diff --git a/client/log.go b/client/log.go
index 0c4e467..ea795b0 100644
--- a/client/log.go
+++ b/client/log.go
@@ -5,10 +5,10 @@ import (
)
// LogFunc is a function that can be used for logging.
-type LogFunc = logging.Func
+//type LogFunc = logging.Func
// LogLevel defines the logging level.
-type LogLevel = logging.Level
+//type LogLevel = logging.Level
// Available logging levels.
const (
@@ -20,4 +20,4 @@ const (
)
// DefaultLogFunc doesn't emit any message.
-func DefaultLogFunc(l LogLevel, format string, a ...interface{}) {}
+func DefaultLogFunc(l logging.Level, format string, a ...interface{}) {}
diff --git a/client/store.go b/client/store.go
index 79c9693..13126ef 100644
--- a/client/store.go
+++ b/client/store.go
@@ -19,16 +19,16 @@ import (
// 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
+//type NodeStore = protocol.NodeStore
// NodeRole identifies the role of a node.
-type NodeRole = protocol.NodeRole
+//type NodeRole = protocol.NodeRole
// NodeInfo holds information about a single server.
-type NodeInfo = protocol.NodeInfo
+//type NodeInfo = protocol.NodeInfo
// InmemNodeStore keeps the list of target dqlite nodes in memory.
-type InmemNodeStore = protocol.InmemNodeStore
+//type InmemNodeStore = protocol.InmemNodeStore
// NewInmemNodeStore creates NodeStore which stores its data in-memory.
var NewInmemNodeStore = protocol.NewInmemNodeStore
@@ -49,7 +49,7 @@ type DatabaseNodeStore struct {
// for the schema, table and column parameters.
//
// It also creates the table if it doesn't exist yet.
-func DefaultNodeStore(filename string) (NodeStore, error) {
+func DefaultNodeStore(filename string) (protocol.NodeStore, error) {
if strings.HasSuffix(filename, ".yaml") {
return NewYamlNodeStore(filename)
}
@@ -108,7 +108,7 @@ func NewNodeStore(db *sql.DB, schema, table, column string, options ...NodeStore
}
// Get the current servers.
-func (d *DatabaseNodeStore) Get(ctx context.Context) ([]NodeInfo, error) {
+func (d *DatabaseNodeStore) Get(ctx context.Context) ([]protocol.NodeInfo, error) {
tx, err := d.db.Begin()
if err != nil {
return nil, errors.Wrap(err, "failed to begin transaction")
@@ -125,14 +125,14 @@ func (d *DatabaseNodeStore) Get(ctx context.Context) ([]NodeInfo, error) {
}
defer rows.Close()
- servers := make([]NodeInfo, 0)
+ servers := make([]protocol.NodeInfo, 0)
for rows.Next() {
var address string
err := rows.Scan(&address)
if err != nil {
return nil, errors.Wrap(err, "failed to fetch server address")
}
- servers = append(servers, NodeInfo{ID: 1, Address: address})
+ servers = append(servers, protocol.NodeInfo{ID: 1, Address: address})
}
if err := rows.Err(); err != nil {
return nil, errors.Wrap(err, "result set failure")
@@ -142,7 +142,7 @@ func (d *DatabaseNodeStore) Get(ctx context.Context) ([]NodeInfo, error) {
}
// Set the servers addresses.
-func (d *DatabaseNodeStore) Set(ctx context.Context, servers []NodeInfo) error {
+func (d *DatabaseNodeStore) Set(ctx context.Context, servers []protocol.NodeInfo) error {
tx, err := d.db.Begin()
if err != nil {
return errors.Wrap(err, "failed to begin transaction")
@@ -179,13 +179,13 @@ func (d *DatabaseNodeStore) Set(ctx context.Context, servers []NodeInfo) error {
// Persists a list addresses of dqlite nodes in a YAML file.
type YamlNodeStore struct {
path string
- servers []NodeInfo
+ servers []protocol.NodeInfo
mu sync.RWMutex
}
// NewYamlNodeStore creates a new YamlNodeStore backed by the given YAML file.
func NewYamlNodeStore(path string) (*YamlNodeStore, error) {
- servers := []NodeInfo{}
+ servers := []protocol.NodeInfo{}
_, err := os.Stat(path)
if err != nil {
@@ -212,7 +212,7 @@ func NewYamlNodeStore(path string) (*YamlNodeStore, error) {
}
// Get the current servers.
-func (s *YamlNodeStore) Get(ctx context.Context) ([]NodeInfo, error) {
+func (s *YamlNodeStore) Get(ctx context.Context) ([]protocol.NodeInfo, error) {
s.mu.RLock()
defer s.mu.RUnlock()
@@ -220,7 +220,7 @@ func (s *YamlNodeStore) Get(ctx context.Context) ([]NodeInfo, error) {
}
// Set the servers addresses.
-func (s *YamlNodeStore) Set(ctx context.Context, servers []NodeInfo) error {
+func (s *YamlNodeStore) Set(ctx context.Context, servers []protocol.NodeInfo) error {
s.mu.Lock()
defer s.mu.Unlock()
diff --git a/cmd/dqlite-demo/dqlite-demo.go b/cmd/dqlite-demo/dqlite-demo.go
index 6748b37..4c84371 100644
--- a/cmd/dqlite-demo/dqlite-demo.go
+++ b/cmd/dqlite-demo/dqlite-demo.go
@@ -13,7 +13,7 @@ import (
"strings"
"github.com/canonical/go-dqlite/app"
- "github.com/canonical/go-dqlite/client"
+ "github.com/canonical/go-dqlite/logging"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"golang.org/x/sys/unix"
@@ -38,7 +38,7 @@ Complete documentation is available at https://github.com/canonical/go-dqlite`,
if err := os.MkdirAll(dir, 0755); err != nil {
return errors.Wrapf(err, "can't create %s", dir)
}
- logFunc := func(l client.LogLevel, format string, a ...interface{}) {
+ logFunc := func(l logging.Level, format string, a ...interface{}) {
if !verbose {
return
}
diff --git a/driver/driver.go b/driver/driver.go
index 4ac8826..841d7dd 100644
--- a/driver/driver.go
+++ b/driver/driver.go
@@ -28,21 +28,22 @@ import (
"github.com/canonical/go-dqlite/client"
"github.com/canonical/go-dqlite/internal/protocol"
+ "github.com/canonical/go-dqlite/logging"
)
// Driver perform queries against a dqlite server.
type Driver struct {
- log client.LogFunc // Log function to use
- store client.NodeStore // Holds addresses of dqlite servers
- context context.Context // Global cancellation context
- connectionTimeout time.Duration // Max time to wait for a new connection
- contextTimeout time.Duration // Default client context timeout.
- clientConfig protocol.Config // Configuration for dqlite client instances
- tracing client.LogLevel // Whether to trace statements
+ log logging.Func // Log function to use
+ store protocol.NodeStore // Holds addresses of dqlite servers
+ context context.Context // Global cancellation context
+ connectionTimeout time.Duration // Max time to wait for a new connection
+ contextTimeout time.Duration // Default client context timeout.
+ clientConfig protocol.Config // Configuration for dqlite client instances
+ tracing logging.Level // Whether to trace statements
}
// Error is returned in case of database errors.
-type Error = protocol.Error
+//type Error = protocol.Error
// Error codes. Values here mostly overlap with native SQLite codes.
const (
@@ -66,17 +67,17 @@ const MaxTupleParams = 255
// Option can be used to tweak driver parameters.
type Option func(*options)
-// NodeStore is a convenience alias of client.NodeStore.
-type NodeStore = client.NodeStore
+// NodeStore is a convenience alias of protocol.NodeStore.
+//type NodeStore = protocol.NodeStore
// NodeInfo is a convenience alias of client.NodeInfo.
-type NodeInfo = client.NodeInfo
+//type NodeInfo = client.NodeInfo
// DefaultNodeStore is a convenience alias of client.DefaultNodeStore.
var DefaultNodeStore = client.DefaultNodeStore
// WithLogFunc sets a custom logging function.
-func WithLogFunc(log client.LogFunc) Option {
+func WithLogFunc(log logging.Func) Option {
return func(options *options) {
options.Log = log
}
@@ -84,10 +85,10 @@ func WithLogFunc(log client.LogFunc) Option {
// DialFunc is a function that can be used to establish a network connection
// with a dqlite node.
-type DialFunc = protocol.DialFunc
+//type DialFunc = protocol.DialFunc
// WithDialFunc sets a custom dial function.
-func WithDialFunc(dial DialFunc) Option {
+func WithDialFunc(dial protocol.DialFunc) Option {
return func(options *options) {
options.Dial = protocol.DialFunc(dial)
}
@@ -172,7 +173,7 @@ func WithContextTimeout(timeout time.Duration) Option {
// WithTracing will emit a log message at the given level every time a
// statement gets executed.
-func WithTracing(level client.LogLevel) Option {
+func WithTracing(level logging.Level) Option {
return func(options *options) {
options.Tracing = level
}
@@ -180,7 +181,7 @@ func WithTracing(level client.LogLevel) Option {
// NewDriver creates a new dqlite driver, which also implements the
// driver.Driver interface.
-func New(store client.NodeStore, options ...Option) (*Driver, error) {
+func New(store protocol.NodeStore, options ...Option) (*Driver, error) {
o := defaultOptions()
for _, option := range options {
@@ -208,7 +209,7 @@ func New(store client.NodeStore, options ...Option) (*Driver, error) {
// Hold configuration options for a dqlite driver.
type options struct {
- Log client.LogFunc
+ Log logging.Func
Dial protocol.DialFunc
AttemptTimeout time.Duration
ConnectionTimeout time.Duration
@@ -217,7 +218,7 @@ type options struct {
ConnectionBackoffCap time.Duration
RetryLimit uint
Context context.Context
- Tracing client.LogLevel
+ Tracing logging.Level
}
// Create a options object with sane defaults.
@@ -328,13 +329,13 @@ var ErrNoAvailableLeader = protocol.ErrNoAvailableLeader
// Conn implements the sql.Conn interface.
type Conn struct {
- log client.LogFunc
+ log logging.Func
protocol *protocol.Protocol
request protocol.Message
response protocol.Message
id uint32 // Database ID.
contextTimeout time.Duration
- tracing client.LogLevel
+ tracing logging.Level
}
// PrepareContext returns a prepared statement, bound to this connection.
@@ -491,7 +492,7 @@ func (c *Conn) Begin() (driver.Tx, error) {
// Tx is a transaction.
type Tx struct {
conn *Conn
- log client.LogFunc
+ log logging.Func
}
// Commit the transaction.
@@ -525,9 +526,9 @@ type Stmt struct {
db uint32
id uint32
params uint64
- log client.LogFunc
+ log logging.Func
sql string // Prepared SQL, only set when tracing
- tracing client.LogLevel
+ tracing logging.Level
}
// Close closes the statement.
@@ -643,7 +644,7 @@ type Rows struct {
rows protocol.Rows
consumed bool
types []string
- log client.LogFunc
+ log logging.Func
}
// Columns returns the names of the columns. The number of
@@ -754,7 +755,7 @@ type unwrappable interface {
Unwrap() error
}
-func driverError(log client.LogFunc, err error) error {
+func driverError(log logging.Func, err error) error {
switch err := errors.Cause(err).(type) {
case syscall.Errno:
log(client.LogDebug, "network connection lost: %v", err)
@@ -785,7 +786,7 @@ func driverError(log client.LogFunc, err error) error {
log(client.LogWarn, "unexpected error code (%d - %s)", err.Code, err.Description)
return driver.ErrBadConn
}
- return Error{
+ return protocol.Error{
Code: int(err.Code),
Message: err.Description,
}
diff --git a/node.go b/node.go
index baa5e94..205a771 100644
--- a/node.go
+++ b/node.go
@@ -6,12 +6,14 @@ import (
"github.com/canonical/go-dqlite/client"
"github.com/canonical/go-dqlite/internal/bindings"
+ "github.com/canonical/go-dqlite/internal/protocol"
+ "github.com/canonical/go-dqlite/logging"
"github.com/pkg/errors"
)
// Node runs a dqlite node.
type Node struct {
- log client.LogFunc // Logger
+ log logging.Func // Logger
server *bindings.Node // Low-level C implementation
acceptCh chan error // Receives connection handling errors
id uint64
@@ -21,7 +23,7 @@ type Node struct {
}
// NodeInfo is a convenience alias for client.NodeInfo.
-type NodeInfo = client.NodeInfo
+//type NodeInfo = client.NodeInfo
// SnapshotParams exposes bindings.SnapshotParams. Used for setting dqlite's
// snapshot parameters.
@@ -29,13 +31,13 @@ type NodeInfo = client.NodeInfo
// taken. The higher this number, the lower the frequency of the snapshots.
// SnapshotParams.Trailing controls how many raft log entries are retained after
// taking a snapshot.
-type SnapshotParams = bindings.SnapshotParams
+//type SnapshotParams = bindings.SnapshotParams
// Option can be used to tweak node parameters.
type Option func(*options)
// WithDialFunc sets a custom dial function for the server.
-func WithDialFunc(dial client.DialFunc) Option {
+func WithDialFunc(dial protocol.DialFunc) Option {
return func(options *options) {
options.DialFunc = dial
}
@@ -63,7 +65,7 @@ func WithFailureDomain(code uint64) Option {
}
// WithSnapshotParams sets the snapshot parameters of the node.
-func WithSnapshotParams(params SnapshotParams) Option {
+func WithSnapshotParams(params bindings.SnapshotParams) Option {
return func(options *options) {
options.SnapshotParams = params
}
@@ -158,14 +160,14 @@ func (s *Node) Start() error {
//
// DEPRECATED: Use ReconfigureMembership instead, which does not require
// instantiating a new Node object.
-func (s *Node) Recover(cluster []NodeInfo) error {
+func (s *Node) Recover(cluster []protocol.NodeInfo) error {
return s.server.Recover(cluster)
}
// Hold configuration options for a dqlite server.
type options struct {
- Log client.LogFunc
- DialFunc client.DialFunc
+ Log logging.Func
+ DialFunc protocol.DialFunc
BindAddress string
NetworkLatency uint64
FailureDomain uint64
@@ -201,7 +203,7 @@ func GenerateID(address string) uint64 {
//
// It forces appending a new configuration to the raft log stored in the given
// directory, effectively replacing the current configuration.
-func ReconfigureMembership(dir string, cluster []NodeInfo) error {
+func ReconfigureMembership(dir string, cluster []protocol.NodeInfo) error {
server, err := bindings.NewNode(context.Background(), 1, "1", dir)
if err != nil {
return err
@@ -218,7 +220,7 @@ func ReconfigureMembership(dir string, cluster []NodeInfo) error {
// In comparision with ReconfigureMembership, this function takes the node role
// into account and makes use of a dqlite API that supports extending the
// NodeInfo struct.
-func ReconfigureMembershipExt(dir string, cluster []NodeInfo) error {
+func ReconfigureMembershipExt(dir string, cluster []protocol.NodeInfo) error {
server, err := bindings.NewNode(context.Background(), 1, "1", dir)
if err != nil {
return err
from go-dqlite.
Closing since the goc toolchain is our primary target and it's not clear what our support policy should be for gccgo; as mentioned above, we're happy to take patches to get gccgo builds working, but it's not a priority for us.
from go-dqlite.
Related Issues (20)
- Expose WithTracing option in app options HOT 3
- Expose an operation to remove a node from the cluster HOT 2
- RowsAffected not returning correct value for UPDATE HOT 4
- Upgrade from yaml.v2 to yaml.v3
- Issues with sharing a connection between statements (?) HOT 4
- Client Error Handling needs improvement HOT 10
- Jepsen failure: EOF when calling Open HOT 1
- Return error in driver.BeginTx if options aren't used/required or incorrect.
- Role re-shuffling for failure domains
- Shortcomings of sortCandidates
- TestIntegration_LeadershipTransfer CI failures HOT 2
- restore dqlite state from snapshot HOT 1
- Change cluster join addresses at runtime HOT 4
- Understanding problem consistency, scalability and leader HOT 5
- Listener for database updates HOT 2
- go-dqlite doesn't support nested or interleaved Query HOT 4
- Issues with two-node clusters
- Nondeterministic nil Logger dereference in driver HOT 1
- Better documentation for `ReconfigureMembership`
- Provide API for finding the most recent segment index
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from go-dqlite.