mirror of
https://github.com/containerd/containerd.git
synced 2026-06-30 19:58:29 +00:00
build(deps): bump go.etcd.io/bbolt from 1.4.3 to 1.5.0
Bumps [go.etcd.io/bbolt](https://github.com/etcd-io/bbolt) from 1.4.3 to 1.5.0. - [Release notes](https://github.com/etcd-io/bbolt/releases) - [Commits](https://github.com/etcd-io/bbolt/compare/v1.4.3...v1.5.0) --- updated-dependencies: - dependency-name: go.etcd.io/bbolt dependency-version: 1.5.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com>
This commit is contained in:
committed by
Maksym Pavlenko
parent
24226cb4c8
commit
7f3f8fffdd
2
go.mod
2
go.mod
@@ -67,7 +67,7 @@ require (
|
||||
github.com/urfave/cli/v2 v2.27.7
|
||||
github.com/vishvananda/netlink v1.3.1
|
||||
github.com/vishvananda/netns v0.0.5
|
||||
go.etcd.io/bbolt v1.4.3
|
||||
go.etcd.io/bbolt v1.5.0
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.69.0
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.69.0
|
||||
go.opentelemetry.io/otel v1.44.0
|
||||
|
||||
4
go.sum
4
go.sum
@@ -351,8 +351,8 @@ github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQ
|
||||
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4=
|
||||
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
go.etcd.io/bbolt v1.4.3 h1:dEadXpI6G79deX5prL3QRNP6JB8UxVkqo4UPnHaNXJo=
|
||||
go.etcd.io/bbolt v1.4.3/go.mod h1:tKQlpPaYCVFctUIgFKFnAlvbmB3tpy1vkTnDWohtc0E=
|
||||
go.etcd.io/bbolt v1.5.0 h1:S7GAl7Fxv12yohbwFfIbQCGDWbQbtDGPET4P/bD4lxU=
|
||||
go.etcd.io/bbolt v1.5.0/go.mod h1:mkltfYE5aUHQxUct9N9V+Kp7aSjFqjgrhcXIS70Lrdk=
|
||||
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
|
||||
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
|
||||
|
||||
4
vendor/go.etcd.io/bbolt/.gitattributes
generated
vendored
Normal file
4
vendor/go.etcd.io/bbolt/.gitattributes
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
# ensure that line endings for Windows builds are properly formatted
|
||||
# see https://github.com/golangci/golangci-lint-action?tab=readme-ov-file#how-to-use
|
||||
# at "Multiple OS Example" section
|
||||
*.go text eol=lf
|
||||
2
vendor/go.etcd.io/bbolt/.go-version
generated
vendored
2
vendor/go.etcd.io/bbolt/.go-version
generated
vendored
@@ -1 +1 @@
|
||||
1.23.12
|
||||
1.25.11
|
||||
|
||||
40
vendor/go.etcd.io/bbolt/.golangci.yaml
generated
vendored
Normal file
40
vendor/go.etcd.io/bbolt/.golangci.yaml
generated
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
formatters:
|
||||
enable:
|
||||
- gci
|
||||
- gofmt
|
||||
- goimports
|
||||
settings: # please keep this alphabetized
|
||||
gci:
|
||||
sections:
|
||||
- standard
|
||||
- default
|
||||
- prefix(go.etcd.io)
|
||||
goimports:
|
||||
local-prefixes:
|
||||
- go.etcd.io # Put imports beginning with prefix after 3rd-party packages.
|
||||
issues:
|
||||
max-same-issues: 0
|
||||
linters:
|
||||
default: none
|
||||
enable: # please keep this alphabetized
|
||||
- errcheck
|
||||
- govet
|
||||
- ineffassign
|
||||
- staticcheck
|
||||
- unused
|
||||
exclusions:
|
||||
presets:
|
||||
- comments
|
||||
- common-false-positives
|
||||
- legacy
|
||||
- std-error-handling
|
||||
settings: # please keep this alphabetized
|
||||
staticcheck:
|
||||
checks:
|
||||
- all
|
||||
- -QF1003 # Convert if/else-if chain to tagged switch
|
||||
- -QF1010 # Convert slice of bytes to string when printing it
|
||||
- -ST1003 # Poorly chosen identifier
|
||||
- -ST1005 # Incorrectly formatted error string
|
||||
- -ST1012 # Poorly chosen name for error variable
|
||||
version: "2"
|
||||
26
vendor/go.etcd.io/bbolt/Makefile
generated
vendored
26
vendor/go.etcd.io/bbolt/Makefile
generated
vendored
@@ -2,6 +2,8 @@ BRANCH=`git rev-parse --abbrev-ref HEAD`
|
||||
COMMIT=`git rev-parse --short HEAD`
|
||||
GOLDFLAGS="-X main.branch $(BRANCH) -X main.commit $(COMMIT)"
|
||||
GOFILES = $(shell find . -name \*.go)
|
||||
REPOSITORY_ROOT := $(shell git rev-parse --show-toplevel)
|
||||
GOTOOLCHAIN ?= go$(shell cat $(REPOSITORY_ROOT)/.go-version)
|
||||
|
||||
TESTFLAGS_RACE=-race=false
|
||||
ifdef ENABLE_RACE
|
||||
@@ -33,7 +35,7 @@ fmt:
|
||||
@!(gofmt -l -s -d ${GOFILES} | grep '[a-z]')
|
||||
|
||||
@echo "Verifying goimports, failures can be fixed with ./scripts/fix.sh"
|
||||
@!(go run golang.org/x/tools/cmd/goimports@latest -l -d ${GOFILES} | grep '[a-z]')
|
||||
@!(go tool golang.org/x/tools/cmd/goimports -l -d ${GOFILES} | grep '[a-z]')
|
||||
|
||||
.PHONY: lint
|
||||
lint:
|
||||
@@ -44,12 +46,12 @@ test:
|
||||
@echo "hashmap freelist test"
|
||||
BBOLT_VERIFY=all TEST_FREELIST_TYPE=hashmap go test -v ${TESTFLAGS} -timeout ${TESTFLAGS_TIMEOUT}
|
||||
BBOLT_VERIFY=all TEST_FREELIST_TYPE=hashmap go test -v ${TESTFLAGS} ./internal/...
|
||||
BBOLT_VERIFY=all TEST_FREELIST_TYPE=hashmap go test -v ${TESTFLAGS} ./cmd/bbolt
|
||||
BBOLT_VERIFY=all TEST_FREELIST_TYPE=hashmap go test -v ${TESTFLAGS} ./cmd/bbolt/...
|
||||
|
||||
@echo "array freelist test"
|
||||
BBOLT_VERIFY=all TEST_FREELIST_TYPE=array go test -v ${TESTFLAGS} -timeout ${TESTFLAGS_TIMEOUT}
|
||||
BBOLT_VERIFY=all TEST_FREELIST_TYPE=array go test -v ${TESTFLAGS} ./internal/...
|
||||
BBOLT_VERIFY=all TEST_FREELIST_TYPE=array go test -v ${TESTFLAGS} ./cmd/bbolt
|
||||
BBOLT_VERIFY=all TEST_FREELIST_TYPE=array go test -v ${TESTFLAGS} ./cmd/bbolt/...
|
||||
|
||||
.PHONY: coverage
|
||||
coverage:
|
||||
@@ -71,16 +73,12 @@ clean: # Clean binaries
|
||||
rm -f ./bin/${BOLT_CMD}
|
||||
|
||||
.PHONY: gofail-enable
|
||||
gofail-enable: install-gofail
|
||||
gofail enable .
|
||||
gofail-enable:
|
||||
go tool go.etcd.io/gofail enable .
|
||||
|
||||
.PHONY: gofail-disable
|
||||
gofail-disable: install-gofail
|
||||
gofail disable .
|
||||
|
||||
.PHONY: install-gofail
|
||||
install-gofail:
|
||||
go install go.etcd.io/gofail
|
||||
gofail-disable:
|
||||
go tool go.etcd.io/gofail disable .
|
||||
|
||||
.PHONY: test-failpoint
|
||||
test-failpoint:
|
||||
@@ -99,10 +97,6 @@ test-robustness: gofail-enable build
|
||||
.PHONY: test-benchmark-compare
|
||||
# Runs benchmark tests on the current git ref and the given REF, and compares
|
||||
# the two.
|
||||
test-benchmark-compare: install-benchstat
|
||||
test-benchmark-compare:
|
||||
@git fetch
|
||||
./scripts/compare_benchmarks.sh $(REF)
|
||||
|
||||
.PHONY: install-benchstat
|
||||
install-benchstat:
|
||||
go install golang.org/x/perf/cmd/benchstat@latest
|
||||
|
||||
1
vendor/go.etcd.io/bbolt/OWNERS
generated
vendored
1
vendor/go.etcd.io/bbolt/OWNERS
generated
vendored
@@ -6,5 +6,6 @@ approvers:
|
||||
- ptabor # Piotr Tabor <piotr.tabor@gmail.com>
|
||||
- spzala # Sahdev Zala <spzala@us.ibm.com>
|
||||
reviewers:
|
||||
- elbehery # Mustafa Elbehery <elbeherymustafa@gmail.com>
|
||||
- fuweid # Wei Fu <fuweid89@gmail.com>
|
||||
- tjungblu # Thomas Jungblut <tjungblu@redhat.com>
|
||||
|
||||
18
vendor/go.etcd.io/bbolt/README.md
generated
vendored
18
vendor/go.etcd.io/bbolt/README.md
generated
vendored
@@ -890,13 +890,19 @@ Here are a few things to note when evaluating and using Bolt:
|
||||
to grow. However, it's important to note that deleting large chunks of data
|
||||
will not allow you to reclaim that space on disk.
|
||||
|
||||
For more information on page allocation, [see this comment][page-allocation].
|
||||
|
||||
* Removing key/values pairs in a bucket during iteration on the bucket using
|
||||
cursor may not work properly. Each time when removing a key/value pair, the
|
||||
cursor may automatically move to the next position if present. When users
|
||||
call `c.Next()` after removing a key, it may skip one key/value pair.
|
||||
Refer to https://github.com/etcd-io/bbolt/pull/611 for more detailed info.
|
||||
|
||||
For more information on page allocation, [see this comment][page-allocation].
|
||||
* Bolt db can be corrupted during the initialization phase due to abrupt power failure.
|
||||
- Please note: This issue can only be reproduced during the very first initialization phase, when there is
|
||||
no existing data in bolt database.
|
||||
- In normal production environment, it is difficult to reproduce this. Once the database file has been initialized, it can no longer occur.
|
||||
- Please refer to this issue for more details: https://github.com/etcd-io/etcd/issues/16596.
|
||||
|
||||
[page-allocation]: https://github.com/boltdb/bolt/issues/308#issuecomment-74811638
|
||||
|
||||
@@ -954,11 +960,16 @@ them via pull request.
|
||||
|
||||
- bbolt might run into data corruption issue on Linux when the feature
|
||||
[ext4: fast commit](https://lwn.net/Articles/842385/), which was introduced in
|
||||
linux kernel version v5.10, is enabled. The fixes to the issue were included in
|
||||
linux kernel version v5.17, please refer to links below,
|
||||
linux kernel version v5.10, is enabled. The fixes to the issue are included in
|
||||
stable LTS patchlevels 5.10.94+ and 5.15.17+ (ftruncate tracking), plus
|
||||
5.15.27+ (ineligible-commit fallback). Linux 5.17 includes these fixes as
|
||||
well, but 5.17 is not an LTS release. Please refer to links below,
|
||||
|
||||
* [ext4: fast commit may miss tracking unwritten range during ftruncate](https://lore.kernel.org/linux-ext4/20211223032337.5198-3-yinxin.x@bytedance.com/)
|
||||
* [5.10.94 stable backport](https://lore.kernel.org/stable/20220124184041.063143682@linuxfoundation.org/)
|
||||
* [5.15.17 stable backport](https://lore.kernel.org/stable/20220124184125.887304707@linuxfoundation.org/)
|
||||
* [ext4: fast commit may not fallback for ineligible commit](https://lore.kernel.org/lkml/202201091544.W5HHEXAp-lkp@intel.com/T/#ma0768815e4b5f671e9e451d578256ef9a76fe30e)
|
||||
* [5.15.27 stable backport](https://lore.kernel.org/stable/20220307091703.544901888@linuxfoundation.org/)
|
||||
* [ext4 updates for 5.17](https://lore.kernel.org/lkml/YdyxjTFaLWif6BCM@mit.edu/)
|
||||
|
||||
Please also refer to the discussion in https://github.com/etcd-io/bbolt/issues/562.
|
||||
@@ -1000,6 +1011,7 @@ Below is a list of public, open source projects that use Bolt:
|
||||
* [GoShort](https://github.com/pankajkhairnar/goShort) - GoShort is a URL shortener written in Golang and BoltDB for persistent key/value storage and for routing it's using high performent HTTPRouter.
|
||||
* [gopherpit](https://github.com/gopherpit/gopherpit) - A web service to manage Go remote import paths with custom domains
|
||||
* [gokv](https://github.com/philippgille/gokv) - Simple key-value store abstraction and implementations for Go (Redis, Consul, etcd, bbolt, BadgerDB, LevelDB, Memcached, DynamoDB, S3, PostgreSQL, MongoDB, CockroachDB and many more)
|
||||
* [goraphdb](https://github.com/mstrYoda/goraphdb) - A graph database provides Cypher query, fluent builder and management UI.
|
||||
* [Gitchain](https://github.com/gitchain/gitchain) - Decentralized, peer-to-peer Git repositories aka "Git meets Bitcoin".
|
||||
* [InfluxDB](https://influxdata.com) - Scalable datastore for metrics, events, and real-time analytics.
|
||||
* [ipLocator](https://github.com/AndreasBriese/ipLocator) - A fast ip-geo-location-server using bolt with bloom filters.
|
||||
|
||||
24
vendor/go.etcd.io/bbolt/bucket.go
generated
vendored
24
vendor/go.etcd.io/bbolt/bucket.go
generated
vendored
@@ -661,16 +661,20 @@ func (b *Bucket) Stats() BucketStats {
|
||||
}
|
||||
} else if p.IsBranchPage() {
|
||||
s.BranchPageN++
|
||||
lastElement := p.BranchPageElement(p.Count() - 1)
|
||||
|
||||
// used totals the used bytes for the page
|
||||
// Add header and all element headers.
|
||||
used := common.PageHeaderSize + (common.BranchPageElementSize * uintptr(p.Count()-1))
|
||||
used := common.PageHeaderSize
|
||||
if p.Count() != 0 {
|
||||
lastElement := p.BranchPageElement(p.Count() - 1)
|
||||
|
||||
// Add all element headers.
|
||||
used += common.BranchPageElementSize * uintptr(p.Count()-1)
|
||||
|
||||
// Add size of all keys and values.
|
||||
// Again, use the fact that last element's position equals to
|
||||
// the total of key, value sizes of all previous elements.
|
||||
used += uintptr(lastElement.Pos() + lastElement.Ksize())
|
||||
}
|
||||
|
||||
// Add size of all keys and values.
|
||||
// Again, use the fact that last element's position equals to
|
||||
// the total of key, value sizes of all previous elements.
|
||||
used += uintptr(lastElement.Pos() + lastElement.Ksize())
|
||||
s.BranchInuse += int(used)
|
||||
s.BranchOverflowN += int(p.Overflow())
|
||||
}
|
||||
@@ -880,7 +884,9 @@ func (b *Bucket) node(pgId common.Pgid, parent *node) *node {
|
||||
// if p isn't nil, then it's an inline bucket.
|
||||
// The pgId must be 0 in this case.
|
||||
common.Verify(func() {
|
||||
common.Assert(pgId == 0, "The page ID (%d) isn't 0 for an inline bucket", pgId)
|
||||
if pgId != 0 {
|
||||
panic(fmt.Sprintf("assertion failed: The page ID (%d) isn't 0 for an inline bucket", pgId))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
3
vendor/go.etcd.io/bbolt/code-of-conduct.md
generated
vendored
Normal file
3
vendor/go.etcd.io/bbolt/code-of-conduct.md
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
# etcd Community Code of Conduct
|
||||
|
||||
Please refer to [etcd Community Code of Conduct](https://github.com/etcd-io/etcd/blob/main/code-of-conduct.md).
|
||||
159
vendor/go.etcd.io/bbolt/db.go
generated
vendored
159
vendor/go.etcd.io/bbolt/db.go
generated
vendored
@@ -36,12 +36,6 @@ const (
|
||||
// All data access is performed through transactions which can be obtained through the DB.
|
||||
// All the functions on DB will return a ErrDatabaseNotOpen if accessed before Open() is called.
|
||||
type DB struct {
|
||||
// Put `stats` at the first field to ensure it's 64-bit aligned. Note that
|
||||
// the first word in an allocated struct can be relied upon to be 64-bit
|
||||
// aligned. Refer to https://pkg.go.dev/sync/atomic#pkg-note-BUG. Also
|
||||
// refer to discussion in https://github.com/etcd-io/bbolt/issues/577.
|
||||
stats Stats
|
||||
|
||||
// When enabled, the database will perform a Check() after every commit.
|
||||
// A panic is issued if the database is in an inconsistent state. This
|
||||
// flag has a large performance impact so it should only be used for
|
||||
@@ -110,6 +104,12 @@ type DB struct {
|
||||
// of truncate() and fsync() when growing the data file.
|
||||
AllocSize int
|
||||
|
||||
// MaxSize is the maximum size (in bytes) allowed for the data file.
|
||||
// If a caller's attempt to add data results in the need to grow
|
||||
// the data file, an error will be returned and the data file will not grow.
|
||||
// <=0 means no limit.
|
||||
MaxSize int
|
||||
|
||||
// Mlock locks database file in memory when set to true.
|
||||
// It prevents major page faults, however used memory can't be reclaimed.
|
||||
//
|
||||
@@ -132,7 +132,7 @@ type DB struct {
|
||||
pageSize int
|
||||
opened bool
|
||||
rwtx *Tx
|
||||
txs []*Tx
|
||||
stats *Stats
|
||||
|
||||
freelist fl.Interface
|
||||
freelistLoad sync.Once
|
||||
@@ -191,12 +191,17 @@ func Open(path string, mode os.FileMode, options *Options) (db *DB, err error) {
|
||||
db.PreLoadFreelist = options.PreLoadFreelist
|
||||
db.FreelistType = options.FreelistType
|
||||
db.Mlock = options.Mlock
|
||||
db.MaxSize = options.MaxSize
|
||||
|
||||
// Set default values for later DB operations.
|
||||
db.MaxBatchSize = common.DefaultMaxBatchSize
|
||||
db.MaxBatchDelay = common.DefaultMaxBatchDelay
|
||||
db.AllocSize = common.DefaultAllocSize
|
||||
|
||||
if !options.NoStatistics {
|
||||
db.stats = new(Stats)
|
||||
}
|
||||
|
||||
if options.Logger == nil {
|
||||
db.logger = getDiscardLogger()
|
||||
} else {
|
||||
@@ -424,7 +429,9 @@ func (db *DB) loadFreelist() {
|
||||
// Read free list from freelist page.
|
||||
db.freelist.Read(db.page(db.meta().Freelist()))
|
||||
}
|
||||
db.stats.FreePageN = db.freelist.FreeCount()
|
||||
if db.stats != nil {
|
||||
db.stats.FreePageN = db.freelist.FreeCount()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -469,6 +476,23 @@ func (db *DB) mmap(minsz int) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
if db.MaxSize > 0 && size > db.MaxSize {
|
||||
// On Windows, the data file is expanded to the full mapped size during mmap,
|
||||
// so we must reject any mmap size larger than the configured max size.
|
||||
//
|
||||
// On other platforms, mmap itself does not grow the file immediately, so the
|
||||
// mapped size may exceed the max size temporarily. The file size limit is
|
||||
// enforced later when the file actually grows.
|
||||
//
|
||||
// In practice, this check mainly applies when opening a database with a large
|
||||
// InitialMmapSize. In all other cases, file growth is already guarded during
|
||||
// page allocation.
|
||||
if size > fileSize && runtime.GOOS == "windows" {
|
||||
db.Logger().Errorf("[GOOS: %s, GOARCH: %s] maximum db size reached, size: %d, db.MaxSize: %d", runtime.GOOS, runtime.GOARCH, size, db.MaxSize)
|
||||
return berrors.ErrMaxSizeReached
|
||||
}
|
||||
}
|
||||
|
||||
if db.Mlock {
|
||||
// Unlock db memory
|
||||
if err := db.munlock(fileSize); err != nil {
|
||||
@@ -545,7 +569,7 @@ func (db *DB) munmap() error {
|
||||
// return errors.New(unmapError)
|
||||
if err := munmap(db); err != nil {
|
||||
db.Logger().Errorf("[GOOS: %s, GOARCH: %s] munmap failed, db.datasz: %d, error: %v", runtime.GOOS, runtime.GOARCH, db.datasz, err)
|
||||
return fmt.Errorf("unmap error: %v", err.Error())
|
||||
return fmt.Errorf("unmap error: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -593,7 +617,7 @@ func (db *DB) munlock(fileSize int) error {
|
||||
// return errors.New(munlockError)
|
||||
if err := munlock(db, fileSize); err != nil {
|
||||
db.Logger().Errorf("[GOOS: %s, GOARCH: %s] munlock failed, fileSize: %d, db.datasz: %d, error: %v", runtime.GOOS, runtime.GOARCH, fileSize, db.datasz, err)
|
||||
return fmt.Errorf("munlock error: %v", err.Error())
|
||||
return fmt.Errorf("munlock error: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -603,7 +627,7 @@ func (db *DB) mlock(fileSize int) error {
|
||||
// return errors.New(mlockError)
|
||||
if err := mlock(db, fileSize); err != nil {
|
||||
db.Logger().Errorf("[GOOS: %s, GOARCH: %s] mlock failed, fileSize: %d, db.datasz: %d, error: %v", runtime.GOOS, runtime.GOARCH, fileSize, db.datasz, err)
|
||||
return fmt.Errorf("mlock error: %v", err.Error())
|
||||
return fmt.Errorf("mlock error: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -794,9 +818,6 @@ func (db *DB) beginTx() (*Tx, error) {
|
||||
t := &Tx{}
|
||||
t.init(db)
|
||||
|
||||
// Keep track of transaction until it closes.
|
||||
db.txs = append(db.txs, t)
|
||||
n := len(db.txs)
|
||||
if db.freelist != nil {
|
||||
db.freelist.AddReadonlyTXID(t.meta.Txid())
|
||||
}
|
||||
@@ -805,10 +826,12 @@ func (db *DB) beginTx() (*Tx, error) {
|
||||
db.metalock.Unlock()
|
||||
|
||||
// Update the transaction stats.
|
||||
db.statlock.Lock()
|
||||
db.stats.TxN++
|
||||
db.stats.OpenTxN = n
|
||||
db.statlock.Unlock()
|
||||
if db.stats != nil {
|
||||
db.statlock.Lock()
|
||||
db.stats.TxN++
|
||||
db.stats.OpenTxN++
|
||||
db.statlock.Unlock()
|
||||
}
|
||||
|
||||
return t, nil
|
||||
}
|
||||
@@ -856,17 +879,6 @@ func (db *DB) removeTx(tx *Tx) {
|
||||
// Use the meta lock to restrict access to the DB object.
|
||||
db.metalock.Lock()
|
||||
|
||||
// Remove the transaction.
|
||||
for i, t := range db.txs {
|
||||
if t == tx {
|
||||
last := len(db.txs) - 1
|
||||
db.txs[i] = db.txs[last]
|
||||
db.txs[last] = nil
|
||||
db.txs = db.txs[:last]
|
||||
break
|
||||
}
|
||||
}
|
||||
n := len(db.txs)
|
||||
if db.freelist != nil {
|
||||
db.freelist.RemoveReadonlyTXID(tx.meta.Txid())
|
||||
}
|
||||
@@ -875,10 +887,12 @@ func (db *DB) removeTx(tx *Tx) {
|
||||
db.metalock.Unlock()
|
||||
|
||||
// Merge statistics.
|
||||
db.statlock.Lock()
|
||||
db.stats.OpenTxN = n
|
||||
db.stats.TxStats.add(&tx.stats)
|
||||
db.statlock.Unlock()
|
||||
if db.stats != nil {
|
||||
db.statlock.Lock()
|
||||
db.stats.OpenTxN--
|
||||
db.stats.TxStats.add(&tx.stats)
|
||||
db.statlock.Unlock()
|
||||
}
|
||||
}
|
||||
|
||||
// Update executes a function within the context of a read-write managed transaction.
|
||||
@@ -1096,9 +1110,13 @@ func (db *DB) Sync() (err error) {
|
||||
// Stats retrieves ongoing performance stats for the database.
|
||||
// This is only updated when a transaction closes.
|
||||
func (db *DB) Stats() Stats {
|
||||
db.statlock.RLock()
|
||||
defer db.statlock.RUnlock()
|
||||
return db.stats
|
||||
var s Stats
|
||||
if db.stats != nil {
|
||||
db.statlock.RLock()
|
||||
s = *db.stats
|
||||
db.statlock.RUnlock()
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// This is for internal access to the raw data bytes from the C cursor, use
|
||||
@@ -1164,9 +1182,33 @@ func (db *DB) allocate(txid common.Txid, count int) (*common.Page, error) {
|
||||
// Resize mmap() if we're at the end.
|
||||
p.SetId(db.rwtx.meta.Pgid())
|
||||
var minsz = int((p.Id()+common.Pgid(count))+1) * db.pageSize
|
||||
if db.MaxSize > 0 {
|
||||
nextAllocSize := minsz
|
||||
nextMmapSize, err := db.mmapSize(minsz)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("mmap size calculation error: %w", err)
|
||||
}
|
||||
if runtime.GOOS == "windows" {
|
||||
// nextAllocSize may not exactly match nextMmapSize.
|
||||
// On Windows, this mismatch may cause the file size to slightly exceed maxSize,
|
||||
// while it is harmless on other platforms.
|
||||
nextAllocSize = nextMmapSize
|
||||
} else {
|
||||
// On non-Windows platforms, the database file is only grown explicitly in grow calls.
|
||||
nextAllocSize = db.growSize(nextMmapSize, nextAllocSize)
|
||||
}
|
||||
if nextAllocSize > db.MaxSize {
|
||||
db.Logger().Errorf("[GOOS: %s, GOARCH: %s] maximum db size reached, minSize: %d (allocSize: %d), db.MaxSize: %d", runtime.GOOS, runtime.GOARCH, minsz, nextAllocSize, db.MaxSize)
|
||||
return nil, berrors.ErrMaxSizeReached
|
||||
}
|
||||
}
|
||||
if minsz >= db.datasz {
|
||||
if err := db.mmap(minsz); err != nil {
|
||||
return nil, fmt.Errorf("mmap allocate error: %s", err)
|
||||
if err == berrors.ErrMaxSizeReached {
|
||||
return nil, err
|
||||
} else {
|
||||
return nil, fmt.Errorf("mmap allocate error: %s", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1190,13 +1232,7 @@ func (db *DB) grow(sz int) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// If the data is smaller than the alloc size then only allocate what's needed.
|
||||
// Once it goes over the allocation size then allocate in chunks.
|
||||
if db.datasz <= db.AllocSize {
|
||||
sz = db.datasz
|
||||
} else {
|
||||
sz += db.AllocSize
|
||||
}
|
||||
sz = db.growSize(db.datasz, sz)
|
||||
|
||||
// Truncate and fsync to ensure file size metadata is flushed.
|
||||
// https://github.com/boltdb/bolt/issues/284
|
||||
@@ -1224,6 +1260,16 @@ func (db *DB) grow(sz int) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *DB) growSize(mmapSize, growSize int) int {
|
||||
// If the data is smaller than the alloc size then only allocate what's needed.
|
||||
// Once it goes over the allocation size then allocate in chunks.
|
||||
if mmapSize <= db.AllocSize {
|
||||
return mmapSize
|
||||
} else {
|
||||
return growSize + db.AllocSize
|
||||
}
|
||||
}
|
||||
|
||||
func (db *DB) IsReadOnly() bool {
|
||||
return db.readOnly
|
||||
}
|
||||
@@ -1243,13 +1289,16 @@ func (db *DB) freepages() []common.Pgid {
|
||||
reachable := make(map[common.Pgid]*common.Page)
|
||||
nofreed := make(map[common.Pgid]bool)
|
||||
ech := make(chan error)
|
||||
|
||||
go func() {
|
||||
for e := range ech {
|
||||
panic(fmt.Sprintf("freepages: failed to get all reachable pages (%v)", e))
|
||||
}
|
||||
defer close(ech)
|
||||
tx.recursivelyCheckBucket(&tx.root, reachable, nofreed, HexKVStringer(), ech)
|
||||
}()
|
||||
tx.recursivelyCheckBucket(&tx.root, reachable, nofreed, HexKVStringer(), ech)
|
||||
close(ech)
|
||||
// following for loop will exit once channel is closed in the above goroutine.
|
||||
// we don't need to wait explictly with a waitgroup
|
||||
for e := range ech {
|
||||
panic(fmt.Sprintf("freepages: failed to get all reachable pages (%v)", e))
|
||||
}
|
||||
|
||||
// TODO: If check bucket reported any corruptions (ech) we shouldn't proceed to freeing the pages.
|
||||
|
||||
@@ -1320,6 +1369,9 @@ type Options struct {
|
||||
// PageSize overrides the default OS page size.
|
||||
PageSize int
|
||||
|
||||
// MaxSize sets the maximum size of the data file. A value <= 0 means no limit.
|
||||
MaxSize int
|
||||
|
||||
// NoSync sets the initial value of DB.NoSync. Normally this can just be
|
||||
// set directly on the DB itself when returned from Open(), but this option
|
||||
// is useful in APIs which expose Options but not the underlying DB.
|
||||
@@ -1336,6 +1388,11 @@ type Options struct {
|
||||
|
||||
// Logger is the logger used for bbolt.
|
||||
Logger Logger
|
||||
|
||||
// NoStatistics turns off statistics collection, Stats method will
|
||||
// return empty structure in this case. This can be beneficial for
|
||||
// performance under high-concurrency read-only transactions.
|
||||
NoStatistics bool
|
||||
}
|
||||
|
||||
func (o *Options) String() string {
|
||||
@@ -1343,8 +1400,8 @@ func (o *Options) String() string {
|
||||
return "{}"
|
||||
}
|
||||
|
||||
return fmt.Sprintf("{Timeout: %s, NoGrowSync: %t, NoFreelistSync: %t, PreLoadFreelist: %t, FreelistType: %s, ReadOnly: %t, MmapFlags: %x, InitialMmapSize: %d, PageSize: %d, NoSync: %t, OpenFile: %p, Mlock: %t, Logger: %p}",
|
||||
o.Timeout, o.NoGrowSync, o.NoFreelistSync, o.PreLoadFreelist, o.FreelistType, o.ReadOnly, o.MmapFlags, o.InitialMmapSize, o.PageSize, o.NoSync, o.OpenFile, o.Mlock, o.Logger)
|
||||
return fmt.Sprintf("{Timeout: %s, NoGrowSync: %t, NoFreelistSync: %t, PreLoadFreelist: %t, FreelistType: %s, ReadOnly: %t, MmapFlags: %x, InitialMmapSize: %d, PageSize: %d, MaxSize: %d, NoSync: %t, OpenFile: %p, Mlock: %t, Logger: %p, NoStatistics: %t}",
|
||||
o.Timeout, o.NoGrowSync, o.NoFreelistSync, o.PreLoadFreelist, o.FreelistType, o.ReadOnly, o.MmapFlags, o.InitialMmapSize, o.PageSize, o.MaxSize, o.NoSync, o.OpenFile, o.Mlock, o.Logger, o.NoStatistics)
|
||||
|
||||
}
|
||||
|
||||
|
||||
3
vendor/go.etcd.io/bbolt/errors/errors.go
generated
vendored
3
vendor/go.etcd.io/bbolt/errors/errors.go
generated
vendored
@@ -69,6 +69,9 @@ var (
|
||||
// ErrValueTooLarge is returned when inserting a value that is larger than MaxValueSize.
|
||||
ErrValueTooLarge = errors.New("value too large")
|
||||
|
||||
// ErrMaxSizeReached is returned when the configured maximum size of the data file is reached.
|
||||
ErrMaxSizeReached = errors.New("database reached maximum size")
|
||||
|
||||
// ErrIncompatibleValue is returned when trying to create or delete a bucket
|
||||
// on an existing non-bucket key or when trying to create or delete a
|
||||
// non-bucket key on an existing bucket key.
|
||||
|
||||
38
vendor/go.etcd.io/bbolt/internal/common/page.go
generated
vendored
38
vendor/go.etcd.io/bbolt/internal/common/page.go
generated
vendored
@@ -74,19 +74,27 @@ func (p *Page) IsFreelistPage() bool {
|
||||
return p.flags == FreelistPageFlag
|
||||
}
|
||||
|
||||
// IsValidPage checks Page flags correctness, only a single proper flag can be used.
|
||||
func (p *Page) IsValidPage() bool {
|
||||
return p.IsBranchPage() ||
|
||||
p.IsLeafPage() ||
|
||||
p.IsMetaPage() ||
|
||||
p.IsFreelistPage()
|
||||
}
|
||||
|
||||
// Meta returns a pointer to the metadata section of the page.
|
||||
func (p *Page) Meta() *Meta {
|
||||
return (*Meta)(UnsafeAdd(unsafe.Pointer(p), unsafe.Sizeof(*p)))
|
||||
}
|
||||
|
||||
func (p *Page) FastCheck(id Pgid) {
|
||||
Assert(p.id == id, "Page expected to be: %v, but self identifies as %v", id, p.id)
|
||||
if p.id != id {
|
||||
panic(fmt.Sprintf("assertion failed: Page expected to be: %v, but self identifies as %v", id, p.id))
|
||||
}
|
||||
// Only one flag of page-type can be set.
|
||||
Assert(p.IsBranchPage() ||
|
||||
p.IsLeafPage() ||
|
||||
p.IsMetaPage() ||
|
||||
p.IsFreelistPage(),
|
||||
"page %v: has unexpected type/flags: %x", p.id, p.flags)
|
||||
if !p.IsValidPage() {
|
||||
panic(fmt.Sprintf("assertion failed: page %v: has unexpected type/flags: %x", p.id, p.flags))
|
||||
}
|
||||
}
|
||||
|
||||
// LeafPageElement retrieves the leaf node by index
|
||||
@@ -122,7 +130,9 @@ func (p *Page) BranchPageElements() []branchPageElement {
|
||||
}
|
||||
|
||||
func (p *Page) FreelistPageCount() (int, int) {
|
||||
Assert(p.IsFreelistPage(), fmt.Sprintf("can't get freelist page count from a non-freelist page: %2x", p.flags))
|
||||
if !p.IsFreelistPage() {
|
||||
panic(fmt.Sprintf("assertion failed: can't get freelist page count from a non-freelist page: %2x", p.flags))
|
||||
}
|
||||
|
||||
// If the page.count is at the max uint16 value (64k) then it's considered
|
||||
// an overflow and the size of the freelist is stored as the first element.
|
||||
@@ -140,7 +150,9 @@ func (p *Page) FreelistPageCount() (int, int) {
|
||||
}
|
||||
|
||||
func (p *Page) FreelistPageIds() []Pgid {
|
||||
Assert(p.IsFreelistPage(), fmt.Sprintf("can't get freelist page IDs from a non-freelist page: %2x", p.flags))
|
||||
if !p.IsFreelistPage() {
|
||||
panic(fmt.Sprintf("assertion failed: can't get freelist page IDs from a non-freelist page: %2x", p.flags))
|
||||
}
|
||||
|
||||
idx, count := p.FreelistPageCount()
|
||||
|
||||
@@ -335,16 +347,16 @@ func (s Pgids) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
||||
func (s Pgids) Less(i, j int) bool { return s[i] < s[j] }
|
||||
|
||||
// Merge returns the sorted union of a and b.
|
||||
func (a Pgids) Merge(b Pgids) Pgids {
|
||||
func (s Pgids) Merge(b Pgids) Pgids {
|
||||
// Return the opposite slice if one is nil.
|
||||
if len(a) == 0 {
|
||||
if len(s) == 0 {
|
||||
return b
|
||||
}
|
||||
if len(b) == 0 {
|
||||
return a
|
||||
return s
|
||||
}
|
||||
merged := make(Pgids, len(a)+len(b))
|
||||
Mergepgids(merged, a, b)
|
||||
merged := make(Pgids, len(s)+len(b))
|
||||
Mergepgids(merged, s, b)
|
||||
return merged
|
||||
}
|
||||
|
||||
|
||||
46
vendor/go.etcd.io/bbolt/internal/freelist/hashmap.go
generated
vendored
46
vendor/go.etcd.io/bbolt/internal/freelist/hashmap.go
generated
vendored
@@ -108,8 +108,10 @@ func (f *hashMap) Allocate(txid common.Txid, n int) common.Pgid {
|
||||
func (f *hashMap) FreeCount() int {
|
||||
common.Verify(func() {
|
||||
expectedFreePageCount := f.hashmapFreeCountSlow()
|
||||
common.Assert(int(f.freePagesCount) == expectedFreePageCount,
|
||||
"freePagesCount (%d) is out of sync with free pages map (%d)", f.freePagesCount, expectedFreePageCount)
|
||||
if int(f.freePagesCount) != expectedFreePageCount {
|
||||
panic(fmt.Sprintf("assertion failed: freePagesCount (%d) is out of sync with free pages map (%d)",
|
||||
f.freePagesCount, expectedFreePageCount))
|
||||
}
|
||||
})
|
||||
return int(f.freePagesCount)
|
||||
}
|
||||
@@ -169,6 +171,11 @@ func (f *hashMap) delSpan(start common.Pgid, size uint64) {
|
||||
}
|
||||
|
||||
func (f *hashMap) mergeSpans(ids common.Pgids) {
|
||||
if len(ids) == 0 {
|
||||
return
|
||||
}
|
||||
sort.Sort(ids)
|
||||
|
||||
common.Verify(func() {
|
||||
ids1Freemap := f.idsFromFreemaps()
|
||||
ids2Forward := f.idsFromForwardMap()
|
||||
@@ -181,7 +188,6 @@ func (f *hashMap) mergeSpans(ids common.Pgids) {
|
||||
panic(fmt.Sprintf("Detected mismatch, f.freemaps: %v, f.backwardMap: %v", f.freemaps, f.backwardMap))
|
||||
}
|
||||
|
||||
sort.Sort(ids)
|
||||
prev := common.Pgid(0)
|
||||
for _, id := range ids {
|
||||
// The ids shouldn't have duplicated free ID.
|
||||
@@ -196,26 +202,36 @@ func (f *hashMap) mergeSpans(ids common.Pgids) {
|
||||
}
|
||||
}
|
||||
})
|
||||
for _, id := range ids {
|
||||
// try to see if we can merge and update
|
||||
f.mergeWithExistingSpan(id)
|
||||
|
||||
start := ids[0]
|
||||
end := ids[0]
|
||||
for i := 1; i < len(ids); i++ {
|
||||
id := ids[i]
|
||||
if id == end+1 {
|
||||
end = id
|
||||
continue
|
||||
}
|
||||
|
||||
f.mergeWithExistingSpan(start, end)
|
||||
start, end = id, id
|
||||
}
|
||||
f.mergeWithExistingSpan(start, end)
|
||||
}
|
||||
|
||||
// mergeWithExistingSpan merges pid to the existing free spans, try to merge it backward and forward
|
||||
func (f *hashMap) mergeWithExistingSpan(pid common.Pgid) {
|
||||
prev := pid - 1
|
||||
next := pid + 1
|
||||
// mergeWithExistingSpan merges free span [start, end] with adjacent existing free spans (both backward and forward).
|
||||
func (f *hashMap) mergeWithExistingSpan(start, end common.Pgid) {
|
||||
prev := start - 1
|
||||
next := end + 1
|
||||
|
||||
preSize, mergeWithPrev := f.backwardMap[prev]
|
||||
nextSize, mergeWithNext := f.forwardMap[next]
|
||||
newStart := pid
|
||||
newSize := uint64(1)
|
||||
newStart := start
|
||||
newSize := uint64(end - start + 1)
|
||||
|
||||
if mergeWithPrev {
|
||||
//merge with previous span
|
||||
start := prev + 1 - common.Pgid(preSize)
|
||||
f.delSpan(start, preSize)
|
||||
// merge with previous span
|
||||
prevStart := prev + 1 - common.Pgid(preSize)
|
||||
f.delSpan(prevStart, preSize)
|
||||
|
||||
newStart -= common.Pgid(preSize)
|
||||
newSize += preSize
|
||||
|
||||
6
vendor/go.etcd.io/bbolt/internal/freelist/shared.go
generated
vendored
6
vendor/go.etcd.io/bbolt/internal/freelist/shared.go
generated
vendored
@@ -220,10 +220,10 @@ func (t *shared) Reload(p *common.Page) {
|
||||
|
||||
func (t *shared) NoSyncReload(pgIds common.Pgids) {
|
||||
// Build a cache of only pending pages.
|
||||
pcache := make(map[common.Pgid]bool)
|
||||
pcache := make(map[common.Pgid]struct{})
|
||||
for _, txp := range t.pending {
|
||||
for _, pendingID := range txp.ids {
|
||||
pcache[pendingID] = true
|
||||
pcache[pendingID] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -231,7 +231,7 @@ func (t *shared) NoSyncReload(pgIds common.Pgids) {
|
||||
// with any pages not in the pending lists.
|
||||
a := []common.Pgid{}
|
||||
for _, id := range pgIds {
|
||||
if !pcache[id] {
|
||||
if _, ok := pcache[id]; !ok {
|
||||
a = append(a, id)
|
||||
}
|
||||
}
|
||||
|
||||
18
vendor/go.etcd.io/bbolt/tx.go
generated
vendored
18
vendor/go.etcd.io/bbolt/tx.go
generated
vendored
@@ -357,13 +357,15 @@ func (tx *Tx) close() {
|
||||
tx.db.rwlock.Unlock()
|
||||
|
||||
// Merge statistics.
|
||||
tx.db.statlock.Lock()
|
||||
tx.db.stats.FreePageN = freelistFreeN
|
||||
tx.db.stats.PendingPageN = freelistPendingN
|
||||
tx.db.stats.FreeAlloc = (freelistFreeN + freelistPendingN) * tx.db.pageSize
|
||||
tx.db.stats.FreelistInuse = freelistAlloc
|
||||
tx.db.stats.TxStats.add(&tx.stats)
|
||||
tx.db.statlock.Unlock()
|
||||
if tx.db.stats != nil {
|
||||
tx.db.statlock.Lock()
|
||||
tx.db.stats.FreePageN = freelistFreeN
|
||||
tx.db.stats.PendingPageN = freelistPendingN
|
||||
tx.db.stats.FreeAlloc = (freelistFreeN + freelistPendingN) * tx.db.pageSize
|
||||
tx.db.stats.FreelistInuse = freelistAlloc
|
||||
tx.db.stats.TxStats.add(&tx.stats)
|
||||
tx.db.statlock.Unlock()
|
||||
}
|
||||
} else {
|
||||
tx.db.removeTx(tx)
|
||||
}
|
||||
@@ -396,7 +398,7 @@ func (tx *Tx) WriteTo(w io.Writer) (n int64, err error) {
|
||||
// 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
|
||||
// WriteFlag 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.
|
||||
|
||||
9
vendor/go.etcd.io/bbolt/tx_check.go
generated
vendored
9
vendor/go.etcd.io/bbolt/tx_check.go
generated
vendored
@@ -36,6 +36,11 @@ func (tx *Tx) Check(options ...CheckOption) <-chan error {
|
||||
}
|
||||
|
||||
func (tx *Tx) check(cfg checkConfig, ch chan error) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ch <- panicked{r}
|
||||
}
|
||||
}()
|
||||
// Force loading free list if opened in ReadOnly mode.
|
||||
tx.db.loadFreelist()
|
||||
|
||||
@@ -281,10 +286,10 @@ func HexKVStringer() KVStringer {
|
||||
|
||||
type hexKvStringer struct{}
|
||||
|
||||
func (_ hexKvStringer) KeyToString(key []byte) string {
|
||||
func (hexKvStringer) KeyToString(key []byte) string {
|
||||
return hex.EncodeToString(key)
|
||||
}
|
||||
|
||||
func (_ hexKvStringer) ValueToString(value []byte) string {
|
||||
func (hexKvStringer) ValueToString(value []byte) string {
|
||||
return hex.EncodeToString(value)
|
||||
}
|
||||
|
||||
4
vendor/modules.txt
vendored
4
vendor/modules.txt
vendored
@@ -576,8 +576,8 @@ github.com/x448/float16
|
||||
# github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1
|
||||
## explicit; go 1.15
|
||||
github.com/xrash/smetrics
|
||||
# go.etcd.io/bbolt v1.4.3
|
||||
## explicit; go 1.23
|
||||
# go.etcd.io/bbolt v1.5.0
|
||||
## explicit; go 1.25.0
|
||||
go.etcd.io/bbolt
|
||||
go.etcd.io/bbolt/errors
|
||||
go.etcd.io/bbolt/internal/common
|
||||
|
||||
Reference in New Issue
Block a user