update to latest bstore, with latest bbolt v1.3.x dependency

This commit is contained in:
Mechiel Lukkien
2025-08-21 17:05:45 +02:00
parent c285e8d2c6
commit a6330066c5
8 changed files with 85 additions and 32 deletions
+2 -2
View File
@@ -5,7 +5,7 @@ go 1.23.0
require (
github.com/mjl-/adns v0.0.0-20250321173553-ab04b05bdfea
github.com/mjl-/autocert v0.0.0-20250321204043-abab2b936e31
github.com/mjl-/bstore v0.0.9
github.com/mjl-/bstore v0.0.10
github.com/mjl-/flate v0.0.0-20250221133712-6372d09eb978
github.com/mjl-/sconf v0.0.7
github.com/mjl-/sherpa v0.6.7
@@ -14,7 +14,7 @@ require (
github.com/mjl-/sherpats v0.0.6
github.com/prometheus/client_golang v1.18.0
github.com/russross/blackfriday/v2 v2.1.0
go.etcd.io/bbolt v1.3.11
go.etcd.io/bbolt v1.3.12
golang.org/x/crypto v0.37.0
golang.org/x/net v0.39.0
golang.org/x/sys v0.32.0
+4 -4
View File
@@ -28,8 +28,8 @@ github.com/mjl-/adns v0.0.0-20250321173553-ab04b05bdfea h1:8dftsVL1tHhRksXzFZRhS
github.com/mjl-/adns v0.0.0-20250321173553-ab04b05bdfea/go.mod h1:rWZMqGA2HoBm5b5q/A5J8u1sSVuEYh6zBz9tMoVs+RU=
github.com/mjl-/autocert v0.0.0-20250321204043-abab2b936e31 h1:6MFGOLPGf6VzHWkKv8waSzJMMS98EFY2LVKPRHffCyo=
github.com/mjl-/autocert v0.0.0-20250321204043-abab2b936e31/go.mod h1:taMFU86abMxKLPV4Bynhv8enbYmS67b8LG80qZv2Qus=
github.com/mjl-/bstore v0.0.9 h1:j8HVXL10Arbk4ujeRGwns8gipH1N1TZn853inQ42FgY=
github.com/mjl-/bstore v0.0.9/go.mod h1:xzIpSfcFosgPJ6h+vsdIt0pzCq4i8hhMuHPQJ0aHQhM=
github.com/mjl-/bstore v0.0.10 h1:fYLQy3EdgXvRHoa8Q3sXMAjZf+uQLRbsh9rYjGep/t4=
github.com/mjl-/bstore v0.0.10/go.mod h1:QzqlAZAVRKwyojCRd9v25viFsMxK5UmIbdxgEyHdK6c=
github.com/mjl-/flate v0.0.0-20250221133712-6372d09eb978 h1:Eg5DfI3/00URzGErujKus6a3O0kyXzF8vjoDZzH/gig=
github.com/mjl-/flate v0.0.0-20250221133712-6372d09eb978/go.mod h1:QBkFtjai3AiQQuUu7pVh6PA06Vd3oa68E+vddf/UBOs=
github.com/mjl-/sconf v0.0.7 h1:bdBcSFZCDFMm/UdBsgNCsjkYmKrSgYwp7rAOoufwHe4=
@@ -70,8 +70,8 @@ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
go.etcd.io/bbolt v1.3.11 h1:yGEzV1wPz2yVCLsD8ZAiGHhHVlczyC9d1rP43/VCRJ0=
go.etcd.io/bbolt v1.3.11/go.mod h1:dksAq7YMXoljX0xu6VF5DMZGbhYYoLUalEiSySYAS4I=
go.etcd.io/bbolt v1.3.12 h1:UAxZAIuJqzFwByP19gZC3zd5robK3FOangrGS+Fdczg=
go.etcd.io/bbolt v1.3.12/go.mod h1:Gi2toLZr1jFkuReJm+yEPn7H8wk6ooptePtHYCbCS1g=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+6 -4
View File
@@ -25,9 +25,10 @@ types, but not pointers to pointers:
- Maps, with keys and values of any supported type, except keys with pointer types.
- Slices and arrays, with elements of any supported type.
- time.Time
- Types that implement binary.MarshalBinary and binary.UnmarshalBinary, useful
for struct types with state in private fields. Do not change the
(Un)marshalBinary method in an incompatible way without a data migration.
- Types that implement [encoding.BinaryMarshaler] and
[encoding.BinaryUnmarshaler], useful for struct types with state in private
fields. Do not change the (Un)marshalBinary method in an incompatible way
without a data migration.
- Structs, with fields of any supported type.
Note: int and uint are stored as int32 and uint32, for compatibility of database
@@ -201,7 +202,8 @@ manage disk pages itself, it cannot as efficiently pack an index page with many
records.
Interface values cannot be stored. This would require storing the type along
with the value. Instead, use a type that is a BinaryMarshaler.
with the value. Instead, use a type that is an [encoding.BinaryMarshaler] and
[encoding.BinaryUnmarshaler].
Values of builtin type "complex" cannot be stored.
+1 -1
View File
@@ -1 +1 @@
1.22.6
1.23.12
+9 -4
View File
@@ -13,6 +13,11 @@ ifdef CPU
endif
TESTFLAGS = $(TESTFLAGS_RACE) $(TESTFLAGS_CPU) $(EXTRA_TESTFLAGS)
TESTFLAGS_TIMEOUT=30m
ifdef TIMEOUT
TESTFLAGS_TIMEOUT=$(TIMEOUT)
endif
.PHONY: fmt
fmt:
!(gofmt -l -s -d $(shell find . -name \*.go) | grep '[a-z]')
@@ -24,21 +29,21 @@ lint:
.PHONY: test
test:
@echo "hashmap freelist test"
TEST_FREELIST_TYPE=hashmap go test -v ${TESTFLAGS} -timeout 30m
TEST_FREELIST_TYPE=hashmap go test -v ${TESTFLAGS} -timeout ${TESTFLAGS_TIMEOUT}
TEST_FREELIST_TYPE=hashmap go test -v ${TESTFLAGS} ./cmd/bbolt
@echo "array freelist test"
TEST_FREELIST_TYPE=array go test -v ${TESTFLAGS} -timeout 30m
TEST_FREELIST_TYPE=array go test -v ${TESTFLAGS} -timeout ${TESTFLAGS_TIMEOUT}
TEST_FREELIST_TYPE=array go test -v ${TESTFLAGS} ./cmd/bbolt
.PHONY: coverage
coverage:
@echo "hashmap freelist test"
TEST_FREELIST_TYPE=hashmap go test -v -timeout 30m \
TEST_FREELIST_TYPE=hashmap go test -v -timeout ${TESTFLAGS_TIMEOUT} \
-coverprofile cover-freelist-hashmap.out -covermode atomic
@echo "array freelist test"
TEST_FREELIST_TYPE=array go test -v -timeout 30m \
TEST_FREELIST_TYPE=array go test -v -timeout ${TESTFLAGS_TIMEOUT} \
-coverprofile cover-freelist-array.out -covermode atomic
BOLT_CMD=bbolt
+6
View File
@@ -1259,6 +1259,12 @@ type Options struct {
// If <=0, the initial map size is 0.
// If initialMmapSize is smaller than the previous database size,
// it takes no effect.
//
// Note: On Windows, due to platform limitations, the database file size
// will be immediately resized to match `InitialMmapSize` (aligned to page size)
// when the DB is opened. On non-Windows platforms, the file size will grow
// dynamically based on the actual amount of written data, regardless of `InitialMmapSize`.
// Refer to https://github.com/etcd-io/bbolt/issues/378#issuecomment-1378121966.
InitialMmapSize int
// PageSize overrides the default OS page size.
+54 -14
View File
@@ -344,16 +344,40 @@ func (tx *Tx) Copy(w io.Writer) error {
// WriteTo writes the entire database to a writer.
// If err == nil then exactly tx.Size() bytes will be written into the writer.
func (tx *Tx) WriteTo(w io.Writer) (n int64, err error) {
// Attempt to open reader with WriteFlag
f, err := tx.db.openFile(tx.db.path, os.O_RDONLY|tx.WriteFlag, 0)
if err != nil {
return 0, err
}
defer func() {
if cerr := f.Close(); err == nil {
err = cerr
var f *os.File
// There is a risk that between the time a read-only transaction
// is created and the time the file is actually opened, the
// underlying db file at tx.db.path may have been replaced
// (e.g. via rename). In that case, opening the file again would
// unexpectedly point to a different file, rather than the one
// the transaction was based on.
//
// To overcome this, we reuse the already opened file handle when
// WritFlag not set. When the WriteFlag is set, we reopen the file
// but verify that it still refers to the same underlying file
// (by device and inode). If it does not, we fall back to
// reusing the existing already opened file handle.
if tx.WriteFlag != 0 {
// Attempt to open reader with WriteFlag
f, err = tx.db.openFile(tx.db.path, os.O_RDONLY|tx.WriteFlag, 0)
if err != nil {
return 0, err
}
}()
if ok, err := sameFile(tx.db.file, f); !ok {
_ = f.Close() // ignore the error
f = tx.db.file
} else {
defer func() {
if cerr := f.Close(); err == nil {
err = cerr
}
}()
}
} else {
f = tx.db.file
}
// Generate a meta page. We use the same page data for both meta pages.
buf := make([]byte, tx.db.pageSize)
@@ -380,13 +404,13 @@ func (tx *Tx) WriteTo(w io.Writer) (n int64, err error) {
return n, fmt.Errorf("meta 1 copy: %s", err)
}
// Move past the meta pages in the file.
if _, err := f.Seek(int64(tx.db.pageSize*2), io.SeekStart); err != nil {
return n, fmt.Errorf("seek: %s", err)
}
// Copy data pages using a SectionReader to avoid affecting f's offset.
dataOffset := int64(tx.db.pageSize * 2)
dataSize := tx.Size() - dataOffset
sr := io.NewSectionReader(f, dataOffset, dataSize)
// Copy data pages.
wn, err := io.CopyN(w, f, tx.Size()-int64(tx.db.pageSize*2))
wn, err := io.CopyN(w, sr, dataSize)
n += wn
if err != nil {
return n, err
@@ -395,6 +419,19 @@ func (tx *Tx) WriteTo(w io.Writer) (n int64, err error) {
return n, nil
}
func sameFile(f1, f2 *os.File) (bool, error) {
fi1, err := f1.Stat()
if err != nil {
return false, fmt.Errorf("failed to get fileInfo of the first file (%s): %w", f1.Name(), err)
}
fi2, err := f2.Stat()
if err != nil {
return false, fmt.Errorf("failed to get fileInfo of the second file (%s): %w", f2.Name(), err)
}
return os.SameFile(fi1, fi2), nil
}
// CopyFile copies the entire database to file at the given path.
// A reader transaction is maintained during the copy so it is safe to continue
// using the database while a copy is in progress.
@@ -509,9 +546,12 @@ func (tx *Tx) writeMeta() error {
tx.meta.write(p)
// Write the meta page to file.
tx.db.metalock.Lock()
if _, err := tx.db.ops.writeAt(buf, int64(p.id)*int64(tx.db.pageSize)); err != nil {
tx.db.metalock.Unlock()
return err
}
tx.db.metalock.Unlock()
if !tx.db.NoSync || IgnoreNoSync {
// gofail: var beforeSyncMetaPage struct{}
if err := fdatasync(tx.db); err != nil {
+3 -3
View File
@@ -16,7 +16,7 @@ github.com/mjl-/adns/internal/singleflight
# github.com/mjl-/autocert v0.0.0-20250321204043-abab2b936e31
## explicit; go 1.20
github.com/mjl-/autocert
# github.com/mjl-/bstore v0.0.9
# github.com/mjl-/bstore v0.0.10
## explicit; go 1.23.0
github.com/mjl-/bstore
# github.com/mjl-/flate v0.0.0-20250221133712-6372d09eb978
@@ -64,8 +64,8 @@ github.com/prometheus/procfs/internal/util
# github.com/russross/blackfriday/v2 v2.1.0
## explicit
github.com/russross/blackfriday/v2
# go.etcd.io/bbolt v1.3.11
## explicit; go 1.22
# go.etcd.io/bbolt v1.3.12
## explicit; go 1.23
go.etcd.io/bbolt
# golang.org/x/crypto v0.37.0
## explicit; go 1.23.0