mirror of
https://github.com/hanzoai/mail.git
synced 2026-09-23 23:53:02 +00:00
update to latest bstore, with latest bbolt v1.3.x dependency
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -1 +1 @@
|
||||
1.22.6
|
||||
1.23.12
|
||||
|
||||
+9
-4
@@ -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
@@ -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
@@ -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 {
|
||||
|
||||
Vendored
+3
-3
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user