updated syscall usage
This commit is contained in:
parent
c9aa60ca28
commit
204aec8135
333 changed files with 12973 additions and 7669 deletions
1
vendor/go.etcd.io/bbolt/.go-version
generated
vendored
Normal file
1
vendor/go.etcd.io/bbolt/.go-version
generated
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
1.22.6
|
||||
13
vendor/go.etcd.io/bbolt/Makefile
generated
vendored
13
vendor/go.etcd.io/bbolt/Makefile
generated
vendored
|
|
@ -41,6 +41,15 @@ coverage:
|
|||
TEST_FREELIST_TYPE=array go test -v -timeout 30m \
|
||||
-coverprofile cover-freelist-array.out -covermode atomic
|
||||
|
||||
BOLT_CMD=bbolt
|
||||
|
||||
build:
|
||||
go build -o bin/${BOLT_CMD} ./cmd/${BOLT_CMD}
|
||||
|
||||
.PHONY: clean
|
||||
clean: # Clean binaries
|
||||
rm -f ./bin/${BOLT_CMD}
|
||||
|
||||
.PHONY: gofail-enable
|
||||
gofail-enable: install-gofail
|
||||
gofail enable .
|
||||
|
|
@ -61,3 +70,7 @@ test-failpoint:
|
|||
@echo "[failpoint] array freelist test"
|
||||
TEST_FREELIST_TYPE=array go test -v ${TESTFLAGS} -timeout 30m ./tests/failpoint
|
||||
|
||||
.PHONY: test-robustness # Running robustness tests requires root permission
|
||||
test-robustness:
|
||||
go test -v ${TESTFLAGS} ./tests/dmflakey -test.root
|
||||
go test -v ${TESTFLAGS} ./tests/robustness -test.root
|
||||
|
|
|
|||
23
vendor/go.etcd.io/bbolt/README.md
generated
vendored
23
vendor/go.etcd.io/bbolt/README.md
generated
vendored
|
|
@ -421,10 +421,19 @@ Prev() Move to the previous key.
|
|||
```
|
||||
|
||||
Each of those functions has a return signature of `(key []byte, value []byte)`.
|
||||
When you have iterated to the end of the cursor then `Next()` will return a
|
||||
`nil` key. You must seek to a position using `First()`, `Last()`, or `Seek()`
|
||||
before calling `Next()` or `Prev()`. If you do not seek to a position then
|
||||
these functions will return a `nil` key.
|
||||
You must seek to a position using `First()`, `Last()`, or `Seek()` before calling
|
||||
`Next()` or `Prev()`. If you do not seek to a position then these functions will
|
||||
return a `nil` key.
|
||||
|
||||
When you have iterated to the end of the cursor, then `Next()` will return a
|
||||
`nil` key and the cursor still points to the last element if present. When you
|
||||
have iterated to the beginning of the cursor, then `Prev()` will return a `nil`
|
||||
key and the cursor still points to the first element if present.
|
||||
|
||||
If you remove key/value pairs during iteration, the cursor may automatically
|
||||
move to the next position if present in current node each time removing a key.
|
||||
When you call `c.Next()` after removing a key, it may skip one key/value pair.
|
||||
Refer to [pull/611](https://github.com/etcd-io/bbolt/pull/611) to get more detailed info.
|
||||
|
||||
During iteration, if the key is non-`nil` but the value is `nil`, that means
|
||||
the key refers to a bucket rather than a value. Use `Bucket.Bucket()` to
|
||||
|
|
@ -850,6 +859,12 @@ 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.
|
||||
|
||||
* 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].
|
||||
|
||||
[page-allocation]: https://github.com/boltdb/bolt/issues/308#issuecomment-74811638
|
||||
|
|
|
|||
15
vendor/go.etcd.io/bbolt/bolt_openbsd.go
generated
vendored
15
vendor/go.etcd.io/bbolt/bolt_openbsd.go
generated
vendored
|
|
@ -1,22 +1,11 @@
|
|||
package bbolt
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
msAsync = 1 << iota // perform asynchronous writes
|
||||
msSync // perform synchronous writes
|
||||
msInvalidate // invalidate cached data
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func msync(db *DB) error {
|
||||
_, _, errno := syscall.Syscall(syscall.SYS_MSYNC, uintptr(unsafe.Pointer(db.data)), uintptr(db.datasz), msInvalidate)
|
||||
if errno != 0 {
|
||||
return errno
|
||||
}
|
||||
return nil
|
||||
return unix.Msync(db.data[:db.datasz], unix.MS_INVALIDATE)
|
||||
}
|
||||
|
||||
func fdatasync(db *DB) error {
|
||||
|
|
|
|||
30
vendor/go.etcd.io/bbolt/bucket.go
generated
vendored
30
vendor/go.etcd.io/bbolt/bucket.go
generated
vendored
|
|
@ -162,12 +162,17 @@ func (b *Bucket) CreateBucket(key []byte) (*Bucket, error) {
|
|||
return nil, ErrBucketNameRequired
|
||||
}
|
||||
|
||||
// Insert into node.
|
||||
// Tip: Use a new variable `newKey` instead of reusing the existing `key` to prevent
|
||||
// it from being marked as leaking, and accordingly cannot be allocated on stack.
|
||||
newKey := cloneBytes(key)
|
||||
|
||||
// Move cursor to correct position.
|
||||
c := b.Cursor()
|
||||
k, _, flags := c.seek(key)
|
||||
k, _, flags := c.seek(newKey)
|
||||
|
||||
// Return an error if there is an existing key.
|
||||
if bytes.Equal(key, k) {
|
||||
if bytes.Equal(newKey, k) {
|
||||
if (flags & bucketLeafFlag) != 0 {
|
||||
return nil, ErrBucketExists
|
||||
}
|
||||
|
|
@ -182,16 +187,14 @@ func (b *Bucket) CreateBucket(key []byte) (*Bucket, error) {
|
|||
}
|
||||
var value = bucket.write()
|
||||
|
||||
// Insert into node.
|
||||
key = cloneBytes(key)
|
||||
c.node().put(key, key, value, 0, bucketLeafFlag)
|
||||
c.node().put(newKey, newKey, value, 0, bucketLeafFlag)
|
||||
|
||||
// Since subbuckets are not allowed on inline buckets, we need to
|
||||
// dereference the inline page, if it exists. This will cause the bucket
|
||||
// to be treated as a regular, non-inline bucket for the rest of the tx.
|
||||
b.page = nil
|
||||
|
||||
return b.Bucket(key), nil
|
||||
return b.Bucket(newKey), nil
|
||||
}
|
||||
|
||||
// CreateBucketIfNotExists creates a new bucket if it doesn't already exist and returns a reference to it.
|
||||
|
|
@ -288,18 +291,23 @@ func (b *Bucket) Put(key []byte, value []byte) error {
|
|||
return ErrValueTooLarge
|
||||
}
|
||||
|
||||
// Insert into node.
|
||||
// Tip: Use a new variable `newKey` instead of reusing the existing `key` to prevent
|
||||
// it from being marked as leaking, and accordingly cannot be allocated on stack.
|
||||
newKey := cloneBytes(key)
|
||||
|
||||
// Move cursor to correct position.
|
||||
c := b.Cursor()
|
||||
k, _, flags := c.seek(key)
|
||||
k, _, flags := c.seek(newKey)
|
||||
|
||||
// Return an error if there is an existing key with a bucket value.
|
||||
if bytes.Equal(key, k) && (flags&bucketLeafFlag) != 0 {
|
||||
if bytes.Equal(newKey, k) && (flags&bucketLeafFlag) != 0 {
|
||||
return ErrIncompatibleValue
|
||||
}
|
||||
|
||||
// Insert into node.
|
||||
key = cloneBytes(key)
|
||||
c.node().put(key, key, value, 0, 0)
|
||||
// gofail: var beforeBucketPut struct{}
|
||||
|
||||
c.node().put(newKey, newKey, value, 0, 0)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
11
vendor/go.etcd.io/bbolt/cursor.go
generated
vendored
11
vendor/go.etcd.io/bbolt/cursor.go
generated
vendored
|
|
@ -71,7 +71,7 @@ func (c *Cursor) Last() (key []byte, value []byte) {
|
|||
|
||||
// If this is an empty page (calling Delete may result in empty pages)
|
||||
// we call prev to find the last page that is not empty
|
||||
for len(c.stack) > 0 && c.stack[len(c.stack)-1].count() == 0 {
|
||||
for len(c.stack) > 1 && c.stack[len(c.stack)-1].count() == 0 {
|
||||
c.prev()
|
||||
}
|
||||
|
||||
|
|
@ -254,6 +254,15 @@ func (c *Cursor) prev() (key []byte, value []byte, flags uint32) {
|
|||
elem.index--
|
||||
break
|
||||
}
|
||||
// If we've hit the beginning, we should stop moving the cursor,
|
||||
// and stay at the first element, so that users can continue to
|
||||
// iterate over the elements in reverse direction by calling `Next`.
|
||||
// We should return nil in such case.
|
||||
// Refer to https://github.com/etcd-io/bbolt/issues/733
|
||||
if len(c.stack) == 1 {
|
||||
c.first()
|
||||
return nil, nil, 0
|
||||
}
|
||||
c.stack = c.stack[:i]
|
||||
}
|
||||
|
||||
|
|
|
|||
54
vendor/go.etcd.io/bbolt/db.go
generated
vendored
54
vendor/go.etcd.io/bbolt/db.go
generated
vendored
|
|
@ -57,6 +57,12 @@ 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
|
||||
|
|
@ -147,7 +153,6 @@ type DB struct {
|
|||
opened bool
|
||||
rwtx *Tx
|
||||
txs []*Tx
|
||||
stats Stats
|
||||
|
||||
freelist *freelist
|
||||
freelistLoad sync.Once
|
||||
|
|
@ -424,7 +429,7 @@ func (db *DB) hasSyncedFreelist() bool {
|
|||
|
||||
// mmap opens the underlying memory-mapped file and initializes the meta references.
|
||||
// minsz is the minimum size that the new mmap can be.
|
||||
func (db *DB) mmap(minsz int) error {
|
||||
func (db *DB) mmap(minsz int) (err error) {
|
||||
db.mmaplock.Lock()
|
||||
defer db.mmaplock.Unlock()
|
||||
|
||||
|
|
@ -459,17 +464,27 @@ func (db *DB) mmap(minsz int) error {
|
|||
}
|
||||
|
||||
// Unmap existing data before continuing.
|
||||
if err := db.munmap(); err != nil {
|
||||
if err = db.munmap(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Memory-map the data file as a byte slice.
|
||||
// gofail: var mapError string
|
||||
// return errors.New(mapError)
|
||||
if err := mmap(db, size); err != nil {
|
||||
if err = mmap(db, size); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Perform unmmap on any error to reset all data fields:
|
||||
// dataref, data, datasz, meta0 and meta1.
|
||||
defer func() {
|
||||
if err != nil {
|
||||
if unmapErr := db.munmap(); unmapErr != nil {
|
||||
err = fmt.Errorf("%w; rollback unmap also failed: %v", err, unmapErr)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
if db.Mlock {
|
||||
// Don't allow swapping of data file
|
||||
if err := db.mlock(fileSize); err != nil {
|
||||
|
|
@ -509,7 +524,7 @@ func (db *DB) munmap() error {
|
|||
// gofail: var unmapError string
|
||||
// return errors.New(unmapError)
|
||||
if err := munmap(db); err != nil {
|
||||
return fmt.Errorf("unmap error: " + err.Error())
|
||||
return fmt.Errorf("unmap error: %v", err.Error())
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
@ -553,15 +568,19 @@ func (db *DB) mmapSize(size int) (int, error) {
|
|||
}
|
||||
|
||||
func (db *DB) munlock(fileSize int) error {
|
||||
// gofail: var munlockError string
|
||||
// return errors.New(munlockError)
|
||||
if err := munlock(db, fileSize); err != nil {
|
||||
return fmt.Errorf("munlock error: " + err.Error())
|
||||
return fmt.Errorf("munlock error: %v", err.Error())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *DB) mlock(fileSize int) error {
|
||||
// gofail: var mlockError string
|
||||
// return errors.New(mlockError)
|
||||
if err := mlock(db, fileSize); err != nil {
|
||||
return fmt.Errorf("mlock error: " + err.Error())
|
||||
return fmt.Errorf("mlock error: %v", err.Error())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
@ -649,9 +668,10 @@ func (db *DB) close() error {
|
|||
// Clear ops.
|
||||
db.ops.writeAt = nil
|
||||
|
||||
var errs []error
|
||||
// Close the mmap.
|
||||
if err := db.munmap(); err != nil {
|
||||
return err
|
||||
errs = append(errs, err)
|
||||
}
|
||||
|
||||
// Close file handles.
|
||||
|
|
@ -660,18 +680,22 @@ func (db *DB) close() error {
|
|||
if !db.readOnly {
|
||||
// Unlock the file.
|
||||
if err := funlock(db); err != nil {
|
||||
return fmt.Errorf("bolt.Close(): funlock error: %w", err)
|
||||
errs = append(errs, fmt.Errorf("bolt.Close(): funlock error: %w", err))
|
||||
}
|
||||
}
|
||||
|
||||
// Close the file descriptor.
|
||||
if err := db.file.Close(); err != nil {
|
||||
return fmt.Errorf("db file close: %s", err)
|
||||
errs = append(errs, fmt.Errorf("db file close: %w", err))
|
||||
}
|
||||
db.file = nil
|
||||
}
|
||||
|
||||
db.path = ""
|
||||
|
||||
if len(errs) > 0 {
|
||||
return errs[0]
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -1135,6 +1159,8 @@ func (db *DB) grow(sz int) error {
|
|||
// https://github.com/boltdb/bolt/issues/284
|
||||
if !db.NoGrowSync && !db.readOnly {
|
||||
if runtime.GOOS != "windows" {
|
||||
// gofail: var resizeFileError string
|
||||
// return errors.New(resizeFileError)
|
||||
if err := db.file.Truncate(int64(sz)); err != nil {
|
||||
return fmt.Errorf("file resize error: %s", err)
|
||||
}
|
||||
|
|
@ -1263,6 +1289,12 @@ var DefaultOptions = &Options{
|
|||
|
||||
// Stats represents statistics about the database.
|
||||
type Stats struct {
|
||||
// Put `TxStats` 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.
|
||||
TxStats TxStats // global, ongoing stats.
|
||||
|
||||
// Freelist stats
|
||||
FreePageN int // total number of free pages on the freelist
|
||||
PendingPageN int // total number of pending pages on the freelist
|
||||
|
|
@ -1272,8 +1304,6 @@ type Stats struct {
|
|||
// Transaction stats
|
||||
TxN int // total number of started read transactions
|
||||
OpenTxN int // number of currently open read transactions
|
||||
|
||||
TxStats TxStats // global, ongoing stats.
|
||||
}
|
||||
|
||||
// Sub calculates and returns the difference between two sets of database stats.
|
||||
|
|
|
|||
19
vendor/go.etcd.io/bbolt/freelist.go
generated
vendored
19
vendor/go.etcd.io/bbolt/freelist.go
generated
vendored
|
|
@ -252,6 +252,14 @@ func (f *freelist) rollback(txid txid) {
|
|||
}
|
||||
// Remove pages from pending list and mark as free if allocated by txid.
|
||||
delete(f.pending, txid)
|
||||
|
||||
// Remove pgids which are allocated by this txid
|
||||
for pgid, tid := range f.allocs {
|
||||
if tid == txid {
|
||||
delete(f.allocs, pgid)
|
||||
}
|
||||
}
|
||||
|
||||
f.mergeSpans(m)
|
||||
}
|
||||
|
||||
|
|
@ -282,9 +290,8 @@ func (f *freelist) read(p *page) {
|
|||
if count == 0 {
|
||||
f.ids = nil
|
||||
} else {
|
||||
var ids []pgid
|
||||
data := unsafeIndex(unsafe.Pointer(p), unsafe.Sizeof(*p), unsafe.Sizeof(ids[0]), idx)
|
||||
unsafeSlice(unsafe.Pointer(&ids), data, count)
|
||||
data := unsafeIndex(unsafe.Pointer(p), unsafe.Sizeof(*p), unsafe.Sizeof(pgid(0)), idx)
|
||||
ids := unsafe.Slice((*pgid)(data), count)
|
||||
|
||||
// copy the ids, so we don't modify on the freelist page directly
|
||||
idsCopy := make([]pgid, count)
|
||||
|
|
@ -322,15 +329,13 @@ func (f *freelist) write(p *page) error {
|
|||
p.count = uint16(l)
|
||||
} else if l < 0xFFFF {
|
||||
p.count = uint16(l)
|
||||
var ids []pgid
|
||||
data := unsafeAdd(unsafe.Pointer(p), unsafe.Sizeof(*p))
|
||||
unsafeSlice(unsafe.Pointer(&ids), data, l)
|
||||
ids := unsafe.Slice((*pgid)(data), l)
|
||||
f.copyall(ids)
|
||||
} else {
|
||||
p.count = 0xFFFF
|
||||
var ids []pgid
|
||||
data := unsafeAdd(unsafe.Pointer(p), unsafe.Sizeof(*p))
|
||||
unsafeSlice(unsafe.Pointer(&ids), data, l+1)
|
||||
ids := unsafe.Slice((*pgid)(data), l+1)
|
||||
ids[0] = pgid(l)
|
||||
f.copyall(ids[1:])
|
||||
}
|
||||
|
|
|
|||
6
vendor/go.etcd.io/bbolt/page.go
generated
vendored
6
vendor/go.etcd.io/bbolt/page.go
generated
vendored
|
|
@ -74,9 +74,8 @@ func (p *page) leafPageElements() []leafPageElement {
|
|||
if p.count == 0 {
|
||||
return nil
|
||||
}
|
||||
var elems []leafPageElement
|
||||
data := unsafeAdd(unsafe.Pointer(p), unsafe.Sizeof(*p))
|
||||
unsafeSlice(unsafe.Pointer(&elems), data, int(p.count))
|
||||
elems := unsafe.Slice((*leafPageElement)(data), int(p.count))
|
||||
return elems
|
||||
}
|
||||
|
||||
|
|
@ -91,9 +90,8 @@ func (p *page) branchPageElements() []branchPageElement {
|
|||
if p.count == 0 {
|
||||
return nil
|
||||
}
|
||||
var elems []branchPageElement
|
||||
data := unsafeAdd(unsafe.Pointer(p), unsafe.Sizeof(*p))
|
||||
unsafeSlice(unsafe.Pointer(&elems), data, int(p.count))
|
||||
elems := unsafe.Slice((*branchPageElement)(data), int(p.count))
|
||||
return elems
|
||||
}
|
||||
|
||||
|
|
|
|||
7
vendor/go.etcd.io/bbolt/tx.go
generated
vendored
7
vendor/go.etcd.io/bbolt/tx.go
generated
vendored
|
|
@ -1,6 +1,7 @@
|
|||
package bbolt
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
|
|
@ -185,6 +186,10 @@ func (tx *Tx) Commit() error {
|
|||
|
||||
// If the high water mark has moved up then attempt to grow the database.
|
||||
if tx.meta.pgid > opgid {
|
||||
_ = errors.New("")
|
||||
// gofail: var lackOfDiskSpace string
|
||||
// tx.rollback()
|
||||
// return errors.New(lackOfDiskSpace)
|
||||
if err := tx.db.grow(int(tx.meta.pgid+1) * tx.db.pageSize); err != nil {
|
||||
tx.rollback()
|
||||
return err
|
||||
|
|
@ -470,6 +475,7 @@ func (tx *Tx) write() error {
|
|||
|
||||
// Ignore file sync if flag is set on DB.
|
||||
if !tx.db.NoSync || IgnoreNoSync {
|
||||
// gofail: var beforeSyncDataPages struct{}
|
||||
if err := fdatasync(tx.db); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -507,6 +513,7 @@ func (tx *Tx) writeMeta() error {
|
|||
return err
|
||||
}
|
||||
if !tx.db.NoSync || IgnoreNoSync {
|
||||
// gofail: var beforeSyncMetaPage struct{}
|
||||
if err := fdatasync(tx.db); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
12
vendor/go.etcd.io/bbolt/unsafe.go
generated
vendored
12
vendor/go.etcd.io/bbolt/unsafe.go
generated
vendored
|
|
@ -1,7 +1,6 @@
|
|||
package bbolt
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
|
|
@ -26,14 +25,3 @@ func unsafeByteSlice(base unsafe.Pointer, offset uintptr, i, j int) []byte {
|
|||
// all), so this is believed to be correct.
|
||||
return (*[maxAllocSize]byte)(unsafeAdd(base, offset))[i:j:j]
|
||||
}
|
||||
|
||||
// unsafeSlice modifies the data, len, and cap of a slice variable pointed to by
|
||||
// the slice parameter. This helper should be used over other direct
|
||||
// manipulation of reflect.SliceHeader to prevent misuse, namely, converting
|
||||
// from reflect.SliceHeader to a Go slice type.
|
||||
func unsafeSlice(slice, data unsafe.Pointer, len int) {
|
||||
s := (*reflect.SliceHeader)(slice)
|
||||
s.Data = uintptr(data)
|
||||
s.Cap = len
|
||||
s.Len = len
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue