Skip to content

Commit 59a3ce5

Browse files
authored
Merge pull request moby#5190 from tonistiigi/db-transactions
db: move DB dependencies to transactor interface
2 parents 3eed13d + 13bd25c commit 59a3ce5

File tree

9 files changed

+79
-31
lines changed

9 files changed

+79
-31
lines changed

cache/metadata/metadata.go

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import (
88
"sync"
99

1010
"github.com/moby/buildkit/util/bklog"
11+
"github.com/moby/buildkit/util/db"
12+
"github.com/moby/buildkit/util/db/boltutil"
1113
"github.com/pkg/errors"
1214
bolt "go.etcd.io/bbolt"
1315
)
@@ -21,18 +23,18 @@ const (
2123
var errNotFound = errors.Errorf("not found")
2224

2325
type Store struct {
24-
db *bolt.DB
26+
db db.DB
2527
}
2628

2729
func NewStore(dbPath string) (*Store, error) {
28-
db, err := bolt.Open(dbPath, 0600, nil)
30+
db, err := boltutil.Open(dbPath, 0600, nil)
2931
if err != nil {
3032
return nil, errors.Wrapf(err, "failed to open database file %s", dbPath)
3133
}
3234
return &Store{db: db}, nil
3335
}
3436

35-
func (s *Store) DB() *bolt.DB {
37+
func (s *Store) DB() db.Transactor {
3638
return s.db
3739
}
3840

@@ -183,21 +185,28 @@ func (s *Store) Get(id string) (*StorageItem, bool) {
183185
si, _ := newStorageItem(id, nil, s)
184186
return si
185187
}
186-
tx, err := s.db.Begin(false)
187-
if err != nil {
188-
return empty(), false
189-
}
190-
defer tx.Rollback()
191-
b := tx.Bucket([]byte(mainBucket))
192-
if b == nil {
188+
189+
var si *StorageItem
190+
if err := s.db.Update(func(tx *bolt.Tx) error {
191+
b := tx.Bucket([]byte(mainBucket))
192+
if b == nil {
193+
return nil
194+
}
195+
b = b.Bucket([]byte(id))
196+
if b == nil {
197+
return nil
198+
}
199+
si, _ = newStorageItem(id, b, s)
200+
return nil
201+
}); err != nil {
193202
return empty(), false
194203
}
195-
b = b.Bucket([]byte(id))
196-
if b == nil {
197-
return empty(), false
204+
205+
if si != nil {
206+
return si, true
198207
}
199-
si, _ := newStorageItem(id, b, s)
200-
return si, true
208+
209+
return empty(), false
201210
}
202211

203212
func (s *Store) Close() error {

cmd/buildkitd/main.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ import (
4646
"github.com/moby/buildkit/util/appdefaults"
4747
"github.com/moby/buildkit/util/archutil"
4848
"github.com/moby/buildkit/util/bklog"
49+
"github.com/moby/buildkit/util/db/boltutil"
4950
"github.com/moby/buildkit/util/grpcerrors"
5051
"github.com/moby/buildkit/util/profiler"
5152
"github.com/moby/buildkit/util/resolver"
@@ -62,7 +63,6 @@ import (
6263
"github.com/pkg/errors"
6364
"github.com/sirupsen/logrus"
6465
"github.com/urfave/cli"
65-
"go.etcd.io/bbolt"
6666
"go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
6767
"go.opentelemetry.io/otel/exporters/prometheus"
6868
"go.opentelemetry.io/otel/propagation"
@@ -804,7 +804,7 @@ func newController(c *cli.Context, cfg *config.Config) (*control.Controller, err
804804
return nil, err
805805
}
806806

807-
historyDB, err := bbolt.Open(filepath.Join(cfg.Root, "history.db"), 0600, nil)
807+
historyDB, err := boltutil.Open(filepath.Join(cfg.Root, "history.db"), 0600, nil)
808808
if err != nil {
809809
return nil, err
810810
}

control/control.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import (
3535
"github.com/moby/buildkit/solver/llbsolver/proc"
3636
"github.com/moby/buildkit/solver/pb"
3737
"github.com/moby/buildkit/util/bklog"
38+
"github.com/moby/buildkit/util/db"
3839
"github.com/moby/buildkit/util/imageutil"
3940
"github.com/moby/buildkit/util/leaseutil"
4041
"github.com/moby/buildkit/util/throttle"
@@ -43,7 +44,6 @@ import (
4344
"github.com/moby/buildkit/worker"
4445
digest "github.com/opencontainers/go-digest"
4546
"github.com/pkg/errors"
46-
"go.etcd.io/bbolt"
4747
sdktrace "go.opentelemetry.io/otel/sdk/trace"
4848
tracev1 "go.opentelemetry.io/proto/otlp/collector/trace/v1"
4949
"golang.org/x/sync/errgroup"
@@ -62,7 +62,7 @@ type Opt struct {
6262
ResolveCacheImporterFuncs map[string]remotecache.ResolveCacheImporterFunc
6363
Entitlements []string
6464
TraceCollector sdktrace.SpanExporter
65-
HistoryDB *bbolt.DB
65+
HistoryDB db.DB
6666
CacheStore *bboltcachestorage.Store
6767
LeaseManager *leaseutil.Manager
6868
ContentStore *containerdsnapshot.Store

solver/bboltcachestorage/storage.go

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import (
99
"github.com/moby/buildkit/identity"
1010
"github.com/moby/buildkit/solver"
1111
"github.com/moby/buildkit/util/bklog"
12+
"github.com/moby/buildkit/util/db"
13+
"github.com/moby/buildkit/util/db/boltutil"
1214
digest "github.com/opencontainers/go-digest"
1315
"github.com/pkg/errors"
1416
bolt "go.etcd.io/bbolt"
@@ -22,11 +24,13 @@ const (
2224
)
2325

2426
type Store struct {
25-
db *bolt.DB
27+
db db.DB
2628
}
2729

2830
func NewStore(dbPath string) (*Store, error) {
29-
db, err := safeOpenDB(dbPath)
31+
db, err := safeOpenDB(dbPath, &bolt.Options{
32+
NoSync: true,
33+
})
3034
if err != nil {
3135
return nil, err
3236
}
@@ -42,7 +46,6 @@ func NewStore(dbPath string) (*Store, error) {
4246
}); err != nil {
4347
return nil, err
4448
}
45-
db.NoSync = true
4649
return &Store{db: db}, nil
4750
}
4851

@@ -465,7 +468,7 @@ func isEmptyBucket(b *bolt.Bucket) bool {
465468

466469
// safeOpenDB opens a bolt database and recovers from panic that
467470
// can be caused by a corrupted database file.
468-
func safeOpenDB(dbPath string) (db *bolt.DB, err error) {
471+
func safeOpenDB(dbPath string, opts *bolt.Options) (db db.DB, err error) {
469472
defer func() {
470473
if r := recover(); r != nil {
471474
err = errors.Errorf("%v", r)
@@ -476,16 +479,16 @@ func safeOpenDB(dbPath string) (db *bolt.DB, err error) {
476479
// then fallback to resetting the database since the database
477480
// may be corrupt.
478481
if err != nil && fileHasContent(dbPath) {
479-
db, err = fallbackOpenDB(dbPath, err)
482+
db, err = fallbackOpenDB(dbPath, opts, err)
480483
}
481484
}()
482-
return openDB(dbPath)
485+
return openDB(dbPath, opts)
483486
}
484487

485488
// fallbackOpenDB performs database recovery and opens the new database
486489
// file when the database fails to open. Called after the first database
487490
// open fails.
488-
func fallbackOpenDB(dbPath string, openErr error) (*bolt.DB, error) {
491+
func fallbackOpenDB(dbPath string, opts *bolt.Options, openErr error) (db.DB, error) {
489492
backupPath := dbPath + "." + identity.NewID() + ".bak"
490493
bklog.L.Errorf("failed to open database file %s, resetting to empty. Old database is backed up to %s. "+
491494
"This error signifies that buildkitd likely crashed or was sigkilled abrubtly, leaving the database corrupted. "+
@@ -496,12 +499,12 @@ func fallbackOpenDB(dbPath string, openErr error) (*bolt.DB, error) {
496499

497500
// Attempt to open the database again. This should be a new database.
498501
// If this fails, it is a permanent error.
499-
return openDB(dbPath)
502+
return openDB(dbPath, opts)
500503
}
501504

502505
// openDB opens a bolt database in user-only read/write mode.
503-
func openDB(dbPath string) (*bolt.DB, error) {
504-
return bolt.Open(dbPath, 0600, nil)
506+
func openDB(dbPath string, opts *bolt.Options) (db.DB, error) {
507+
return boltutil.Open(dbPath, 0600, opts)
505508
}
506509

507510
// fileHasContent checks if we have access to the file with appropriate

solver/bboltcachestorage/storage_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ func TestBoltCacheStorage(t *testing.T) {
1616
st, err := NewStore(filepath.Join(tmpDir, "cache.db"))
1717
require.NoError(t, err)
1818
t.Cleanup(func() {
19-
require.NoError(t, st.db.Close())
19+
require.NoError(t, st.Close())
2020
})
2121

2222
return st

solver/llbsolver/history.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"github.com/moby/buildkit/cmd/buildkitd/config"
2323
"github.com/moby/buildkit/identity"
2424
containerdsnapshot "github.com/moby/buildkit/snapshot/containerd"
25+
"github.com/moby/buildkit/util/db"
2526
"github.com/moby/buildkit/util/grpcerrors"
2627
"github.com/moby/buildkit/util/iohelper"
2728
"github.com/moby/buildkit/util/leaseutil"
@@ -39,7 +40,7 @@ const (
3940
)
4041

4142
type HistoryQueueOpt struct {
42-
DB *bolt.DB
43+
DB db.Transactor
4344
LeaseManager *leaseutil.Manager
4445
ContentStore *containerdsnapshot.Store
4546
CleanConfig *config.HistoryConfig

util/db/boltutil/db.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package boltutil
2+
3+
import (
4+
"io/fs"
5+
6+
"github.com/moby/buildkit/util/db"
7+
bolt "go.etcd.io/bbolt"
8+
)
9+
10+
func Open(p string, mode fs.FileMode, options *bolt.Options) (db.DB, error) {
11+
bdb, err := bolt.Open(p, mode, options)
12+
if err != nil {
13+
return nil, err
14+
}
15+
return bdb, nil
16+
}

util/db/db.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package db
2+
3+
import "io"
4+
5+
type DB interface {
6+
io.Closer
7+
Transactor
8+
}

util/db/transactor.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package db
2+
3+
import (
4+
bolt "go.etcd.io/bbolt"
5+
)
6+
7+
// Transactor is the database interface for running transactions
8+
type Transactor interface {
9+
View(fn func(*bolt.Tx) error) error
10+
Update(fn func(*bolt.Tx) error) error
11+
}

0 commit comments

Comments
 (0)