From 246a78f150e1332a28d9ccfb9def196abde64b9a Mon Sep 17 00:00:00 2001 From: Mateusz Urbanek Date: Wed, 8 May 2024 09:15:45 +0200 Subject: [PATCH] feat: support RISC-V 64 Signed-off-by: Mateusz Urbanek --- go.mod | 10 ++- go.sum | 21 +++++- pkg/drivers/sqlite/sqlite.go | 116 ---------------------------- pkg/drivers/sqlite/sqlite_cgo.go | 117 +++++++++++++++++++++++++++++ pkg/drivers/sqlite/sqlite_nocgo.go | 105 ++++++++++++++++++++++++-- scripts/build | 2 + 6 files changed, 246 insertions(+), 125 deletions(-) create mode 100644 pkg/drivers/sqlite/sqlite_cgo.go diff --git a/go.mod b/go.mod index a69b4280..de3df1d5 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ go 1.19 require ( github.com/Rican7/retry v0.1.0 github.com/canonical/go-dqlite v1.5.1 + github.com/glebarez/go-sqlite v1.22.0 github.com/go-sql-driver/mysql v1.7.1 github.com/jackc/pgerrcode v0.0.0-20220416144525-469b46aa5efa github.com/jackc/pgx/v5 v5.5.4 @@ -27,6 +28,7 @@ require ( google.golang.org/grpc v1.56.3 k8s.io/apimachinery v0.28.6 k8s.io/client-go v0.28.6 + modernc.org/sqlite v1.28.0 ) require ( @@ -36,13 +38,14 @@ require ( github.com/coreos/go-semver v0.3.0 // indirect github.com/coreos/go-systemd/v22 v22.3.2 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect - github.com/dustin/go-humanize v1.0.0 // indirect + github.com/dustin/go-humanize v1.0.1 // indirect github.com/ghodss/yaml v1.0.0 // indirect github.com/go-logr/logr v1.2.4 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang-jwt/jwt/v4 v4.4.2 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/google/btree v1.0.1 // indirect + github.com/google/uuid v1.5.0 // indirect github.com/gorilla/websocket v1.4.2 // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect @@ -52,6 +55,7 @@ require ( github.com/jackc/puddle/v2 v2.2.1 // indirect github.com/jonboulle/clockwork v0.2.2 // indirect github.com/json-iterator/go v1.1.12 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/minio/highwayhash v1.0.2 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect @@ -62,6 +66,7 @@ require ( github.com/prometheus/client_model v0.4.0 // indirect github.com/prometheus/common v0.44.0 // indirect github.com/prometheus/procfs v0.10.1 // indirect + github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/russross/blackfriday/v2 v2.0.1 // indirect github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect github.com/soheilhy/cmux v0.1.5 // indirect @@ -94,5 +99,8 @@ require ( gopkg.in/yaml.v2 v2.4.0 // indirect k8s.io/klog/v2 v2.100.1 // indirect k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 // indirect + modernc.org/libc v1.37.6 // indirect + modernc.org/mathutil v1.6.0 // indirect + modernc.org/memory v1.7.2 // indirect sigs.k8s.io/yaml v1.3.0 // indirect ) diff --git a/go.sum b/go.sum index d5db3f94..d0cc3af0 100644 --- a/go.sum +++ b/go.sum @@ -37,8 +37,9 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsr github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= @@ -50,6 +51,8 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7 github.com/envoyproxy/protoc-gen-validate v0.10.1 h1:c0g45+xCJhdgFGw7a5QAfdS4byAbud7miNWJ1WwEVf8= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/glebarez/go-sqlite v1.22.0 h1:uAcMJhaA6r3LHMTFgP0SifzgXg46yJkgxqyuyec+ruQ= +github.com/glebarez/go-sqlite v1.22.0/go.mod h1:PlBIdHe0+aUEFn+r2/uthrWq4FxbzugL0L8Li6yQJbc= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= @@ -92,7 +95,10 @@ github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU= +github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= @@ -124,6 +130,8 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxv github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-sqlite3 v1.14.19 h1:fhGleo2h1p8tVChob4I9HpmVFIAkKGpiukdrgQbWfGI= github.com/mattn/go-sqlite3 v1.14.19/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= @@ -168,6 +176,8 @@ github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+Pymzi github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= github.com/rancher/wrangler/v2 v2.1.4 h1:ohov0i6A9dJHHO6sjfsH4Dqv93ZTdm5lIJVJdPzVdQc= github.com/rancher/wrangler/v2 v2.1.4/go.mod h1:af5OaGU/COgreQh1mRbKiUI64draT2NN34uk+PALFY8= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= @@ -294,6 +304,7 @@ golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220111092808-5a964db01320/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -375,5 +386,13 @@ k8s.io/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg= k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 h1:qY1Ad8PODbnymg2pRbkyMT/ylpTrCM8P2RJ0yroCyIk= k8s.io/utils v0.0.0-20230406110748-d93618cff8a2/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +modernc.org/libc v1.37.6 h1:orZH3c5wmhIQFTXF+Nt+eeauyd+ZIt2BX6ARe+kD+aw= +modernc.org/libc v1.37.6/go.mod h1:YAXkAZ8ktnkCKaN9sw/UDeUVkGYJ/YquGO4FTi5nmHE= +modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4= +modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo= +modernc.org/memory v1.7.2 h1:Klh90S215mmH8c9gO98QxQFsY+W451E8AnzjoE2ee1E= +modernc.org/memory v1.7.2/go.mod h1:NO4NVCQy0N7ln+T9ngWqOQfi7ley4vpwvARR+Hjw95E= +modernc.org/sqlite v1.28.0 h1:Zx+LyDDmXczNnEQdvPuEfcFVA2ZPyaD7UCZDjef3BHQ= +modernc.org/sqlite v1.28.0/go.mod h1:Qxpazz0zH8Z1xCFyi5GSL3FzbtZ3fvbjmywNogldEW0= sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= diff --git a/pkg/drivers/sqlite/sqlite.go b/pkg/drivers/sqlite/sqlite.go index 1313b298..329a6d8a 100644 --- a/pkg/drivers/sqlite/sqlite.go +++ b/pkg/drivers/sqlite/sqlite.go @@ -1,29 +1,5 @@ -//go:build cgo -// +build cgo - package sqlite -import ( - "context" - "database/sql" - "fmt" - "os" - "time" - - "github.com/k3s-io/kine/pkg/drivers/generic" - "github.com/k3s-io/kine/pkg/logstructured" - "github.com/k3s-io/kine/pkg/logstructured/sqllog" - "github.com/k3s-io/kine/pkg/server" - "github.com/k3s-io/kine/pkg/util" - "github.com/mattn/go-sqlite3" - "github.com/pkg/errors" - "github.com/prometheus/client_golang/prometheus" - "github.com/sirupsen/logrus" - - // sqlite db driver - _ "github.com/mattn/go-sqlite3" -) - var ( schema = []string{ `CREATE TABLE IF NOT EXISTS kine @@ -46,95 +22,3 @@ var ( `PRAGMA wal_checkpoint(TRUNCATE)`, } ) - -func New(ctx context.Context, dataSourceName string, connPoolConfig generic.ConnectionPoolConfig, metricsRegisterer prometheus.Registerer) (server.Backend, error) { - backend, _, err := NewVariant(ctx, "sqlite3", dataSourceName, connPoolConfig, metricsRegisterer) - return backend, err -} - -func NewVariant(ctx context.Context, driverName, dataSourceName string, connPoolConfig generic.ConnectionPoolConfig, metricsRegisterer prometheus.Registerer) (server.Backend, *generic.Generic, error) { - if dataSourceName == "" { - if err := os.MkdirAll("./db", 0700); err != nil { - return nil, nil, err - } - dataSourceName = "./db/state.db?_journal=WAL&cache=shared&_busy_timeout=30000" - } - - dialect, err := generic.Open(ctx, driverName, dataSourceName, connPoolConfig, "?", false, metricsRegisterer) - if err != nil { - return nil, nil, err - } - - dialect.LastInsertID = true - dialect.GetSizeSQL = `SELECT SUM(pgsize) FROM dbstat` - dialect.CompactSQL = ` - DELETE FROM kine AS kv - WHERE - kv.id IN ( - SELECT kp.prev_revision AS id - FROM kine AS kp - WHERE - kp.name != 'compact_rev_key' AND - kp.prev_revision != 0 AND - kp.id <= ? - UNION - SELECT kd.id AS id - FROM kine AS kd - WHERE - kd.deleted != 0 AND - kd.id <= ? - )` - dialect.PostCompactSQL = `PRAGMA wal_checkpoint(FULL)` - dialect.TranslateErr = func(err error) error { - if err, ok := err.(sqlite3.Error); ok && err.ExtendedCode == sqlite3.ErrConstraintUnique { - return server.ErrKeyExists - } - return err - } - dialect.ErrCode = func(err error) string { - if err == nil { - return "" - } - if err, ok := err.(sqlite3.Error); ok { - return fmt.Sprint(err.ExtendedCode) - } - return err.Error() - } - - // this is the first SQL that will be executed on a new DB conn so - // loop on failure here because in the case of dqlite it could still be initializing - for i := 0; i < 300; i++ { - err = setup(dialect.DB) - if err == nil { - break - } - logrus.Errorf("failed to setup db: %v", err) - select { - case <-ctx.Done(): - return nil, nil, ctx.Err() - case <-time.After(time.Second): - } - time.Sleep(time.Second) - } - if err != nil { - return nil, nil, errors.Wrap(err, "setup db") - } - - dialect.Migrate(context.Background()) - return logstructured.New(sqllog.New(dialect)), dialect, nil -} - -func setup(db *sql.DB) error { - logrus.Infof("Configuring database table schema and indexes, this may take a moment...") - - for _, stmt := range schema { - logrus.Tracef("SETUP EXEC : %v", util.Stripped(stmt)) - _, err := db.Exec(stmt) - if err != nil { - return err - } - } - - logrus.Infof("Database tables and indexes are up to date") - return nil -} diff --git a/pkg/drivers/sqlite/sqlite_cgo.go b/pkg/drivers/sqlite/sqlite_cgo.go new file mode 100644 index 00000000..e7f39858 --- /dev/null +++ b/pkg/drivers/sqlite/sqlite_cgo.go @@ -0,0 +1,117 @@ +//go:build cgo +// +build cgo + +package sqlite + +import ( + "context" + "database/sql" + "fmt" + "os" + "time" + + "github.com/k3s-io/kine/pkg/drivers/generic" + "github.com/k3s-io/kine/pkg/logstructured" + "github.com/k3s-io/kine/pkg/logstructured/sqllog" + "github.com/k3s-io/kine/pkg/server" + "github.com/k3s-io/kine/pkg/util" + "github.com/mattn/go-sqlite3" + "github.com/pkg/errors" + "github.com/prometheus/client_golang/prometheus" + "github.com/sirupsen/logrus" + + // sqlite db driver + _ "github.com/mattn/go-sqlite3" +) + +func New(ctx context.Context, dataSourceName string, connPoolConfig generic.ConnectionPoolConfig, metricsRegisterer prometheus.Registerer) (server.Backend, error) { + backend, _, err := NewVariant(ctx, "sqlite3", dataSourceName, connPoolConfig, metricsRegisterer) + return backend, err +} + +func NewVariant(ctx context.Context, driverName, dataSourceName string, connPoolConfig generic.ConnectionPoolConfig, metricsRegisterer prometheus.Registerer) (server.Backend, *generic.Generic, error) { + if dataSourceName == "" { + if err := os.MkdirAll("./db", 0700); err != nil { + return nil, nil, err + } + dataSourceName = "./db/state.db?_journal=WAL&cache=shared&_busy_timeout=30000" + } + + dialect, err := generic.Open(ctx, driverName, dataSourceName, connPoolConfig, "?", false, metricsRegisterer) + if err != nil { + return nil, nil, err + } + + dialect.LastInsertID = true + dialect.GetSizeSQL = `SELECT SUM(pgsize) FROM dbstat` + dialect.CompactSQL = ` + DELETE FROM kine AS kv + WHERE + kv.id IN ( + SELECT kp.prev_revision AS id + FROM kine AS kp + WHERE + kp.name != 'compact_rev_key' AND + kp.prev_revision != 0 AND + kp.id <= ? + UNION + SELECT kd.id AS id + FROM kine AS kd + WHERE + kd.deleted != 0 AND + kd.id <= ? + )` + dialect.PostCompactSQL = `PRAGMA wal_checkpoint(FULL)` + dialect.TranslateErr = func(err error) error { + if err, ok := err.(sqlite3.Error); ok && err.ExtendedCode == sqlite3.ErrConstraintUnique { + return server.ErrKeyExists + } + return err + } + dialect.ErrCode = func(err error) string { + if err == nil { + return "" + } + if err, ok := err.(sqlite3.Error); ok { + return fmt.Sprint(err.ExtendedCode) + } + return err.Error() + } + + // this is the first SQL that will be executed on a new DB conn so + // loop on failure here because in the case of dqlite it could still be initializing + for i := 0; i < 300; i++ { + err = setup(dialect.DB) + if err == nil { + break + } + logrus.Errorf("failed to setup db: %v", err) + select { + case <-ctx.Done(): + return nil, nil, ctx.Err() + case <-time.After(time.Second): + } + time.Sleep(time.Second) + } + if err != nil { + return nil, nil, errors.Wrap(err, "setup db") + } + + dialect.Migrate(context.Background()) + return logstructured.New(sqllog.New(dialect)), dialect, nil +} + +func setup(db *sql.DB) error { + logrus.Infof("Configuring database table schema and indexes, this may take a moment...") + + for _, stmt := range schema { + logrus.Tracef("SETUP EXEC : %v", util.Stripped(stmt)) + _, err := db.Exec(stmt) + if err != nil { + return err + } + } + + logrus.Infof("Database tables and indexes are up to date") + return nil +} diff --git a/pkg/drivers/sqlite/sqlite_nocgo.go b/pkg/drivers/sqlite/sqlite_nocgo.go index d730b406..dd59911d 100644 --- a/pkg/drivers/sqlite/sqlite_nocgo.go +++ b/pkg/drivers/sqlite/sqlite_nocgo.go @@ -6,23 +6,114 @@ package sqlite import ( "context" "database/sql" - "errors" + "fmt" + "os" + "time" + "github.com/glebarez/go-sqlite" "github.com/k3s-io/kine/pkg/drivers/generic" + "github.com/k3s-io/kine/pkg/logstructured" + "github.com/k3s-io/kine/pkg/logstructured/sqllog" "github.com/k3s-io/kine/pkg/server" + "github.com/k3s-io/kine/pkg/util" + "github.com/pkg/errors" "github.com/prometheus/client_golang/prometheus" -) + "github.com/sirupsen/logrus" + libsqlite "modernc.org/sqlite/lib" -var errNoCgo = errors.New("this binary is built without CGO, sqlite is disabled") + // sqlite db driver + _ "github.com/glebarez/go-sqlite" +) func New(ctx context.Context, dataSourceName string, connPoolConfig generic.ConnectionPoolConfig, metricsRegisterer prometheus.Registerer) (server.Backend, error) { - return nil, errNoCgo + sqlite.RegisterAsSQLITE3() + backend, _, err := NewVariant(ctx, "sqlite3", dataSourceName, connPoolConfig, metricsRegisterer) + return backend, err } -func NewVariant(driverName, dataSourceName string, connPoolConfig generic.ConnectionPoolConfig, metricsRegisterer prometheus.Registerer) (server.Backend, *generic.Generic, error) { - return nil, nil, errNoCgo +func NewVariant(ctx context.Context, driverName, dataSourceName string, connPoolConfig generic.ConnectionPoolConfig, metricsRegisterer prometheus.Registerer) (server.Backend, *generic.Generic, error) { + if dataSourceName == "" { + if err := os.MkdirAll("./db", 0700); err != nil { + return nil, nil, err + } + dataSourceName = "./db/state.db?_journal=WAL&cache=shared&_busy_timeout=30000" + } + + dialect, err := generic.Open(ctx, driverName, dataSourceName, connPoolConfig, "?", false, metricsRegisterer) + if err != nil { + return nil, nil, err + } + + dialect.LastInsertID = true + dialect.GetSizeSQL = `SELECT SUM(pgsize) FROM dbstat` + dialect.CompactSQL = ` + DELETE FROM kine AS kv + WHERE + kv.id IN ( + SELECT kp.prev_revision AS id + FROM kine AS kp + WHERE + kp.name != 'compact_rev_key' AND + kp.prev_revision != 0 AND + kp.id <= ? + UNION + SELECT kd.id AS id + FROM kine AS kd + WHERE + kd.deleted != 0 AND + kd.id <= ? + )` + dialect.PostCompactSQL = `PRAGMA wal_checkpoint(FULL)` + dialect.TranslateErr = func(err error) error { + if err, ok := err.(*sqlite.Error); ok && err.Code() == libsqlite.SQLITE_CONSTRAINT_UNIQUE { + return server.ErrKeyExists + } + return err + } + dialect.ErrCode = func(err error) string { + if err == nil { + return "" + } + if err, ok := err.(*sqlite.Error); ok { + return fmt.Sprint(err.Code()) + } + return err.Error() + } + + // this is the first SQL that will be executed on a new DB conn so + // loop on failure here because in the case of dqlite it could still be initializing + for i := 0; i < 300; i++ { + err = setup(dialect.DB) + if err == nil { + break + } + logrus.Errorf("failed to setup db: %v", err) + select { + case <-ctx.Done(): + return nil, nil, ctx.Err() + case <-time.After(time.Second): + } + time.Sleep(time.Second) + } + if err != nil { + return nil, nil, errors.Wrap(err, "setup db") + } + + dialect.Migrate(context.Background()) + return logstructured.New(sqllog.New(dialect)), dialect, nil } func setup(db *sql.DB) error { - return errNoCgo + logrus.Infof("Configuring database table schema and indexes, this may take a moment...") + + for _, stmt := range schema { + logrus.Tracef("SETUP EXEC : %v", util.Stripped(stmt)) + _, err := db.Exec(stmt) + if err != nil { + return err + } + } + + logrus.Infof("Database tables and indexes are up to date") + return nil } diff --git a/scripts/build b/scripts/build index 684c7fea..fb74b203 100755 --- a/scripts/build +++ b/scripts/build @@ -10,6 +10,8 @@ mkdir -p bin if [ ${ARCH} = armv7l ] || [ ${ARCH} = arm ]; then export GOARCH="arm" export GOARM="7" +elif [ ${ARCH} = riscv64 ]; then + export GOARCH="riscv64" fi if [ "$(uname)" = "Linux" ]; then