diff --git a/bolt_unix.go b/bolt_unix.go index e901e56..deb7e7c 100644 --- a/bolt_unix.go +++ b/bolt_unix.go @@ -11,7 +11,7 @@ import ( "golang.org/x/sys/unix" - "go.etcd.io/bbolt/internal/common" + "go.etcd.io/bbolt/errors" ) // flock acquires an advisory lock on a file descriptor. @@ -38,7 +38,7 @@ func flock(db *DB, exclusive bool, timeout time.Duration) error { // If we timed out then return an error. if timeout != 0 && time.Since(t) > timeout-flockRetryTimeout { - return common.ErrTimeout + return errors.ErrTimeout } // Wait for a bit and try again. diff --git a/bolt_windows.go b/bolt_windows.go index 1981c64..020f1a1 100644 --- a/bolt_windows.go +++ b/bolt_windows.go @@ -9,7 +9,7 @@ import ( "golang.org/x/sys/windows" - "go.etcd.io/bbolt/internal/common" + "go.etcd.io/bbolt/errors" ) // fdatasync flushes written data to a file descriptor. @@ -44,7 +44,7 @@ func flock(db *DB, exclusive bool, timeout time.Duration) error { // If we timed oumercit then return an error. if timeout != 0 && time.Since(t) > timeout-flockRetryTimeout { - return common.ErrTimeout + return errors.ErrTimeout } // Wait for a bit and try again. diff --git a/bucket.go b/bucket.go index 52f9790..b1c1b85 100644 --- a/bucket.go +++ b/bucket.go @@ -5,6 +5,7 @@ import ( "fmt" "unsafe" + "go.etcd.io/bbolt/errors" "go.etcd.io/bbolt/internal/common" ) @@ -146,11 +147,11 @@ func (b *Bucket) openBucket(value []byte) *Bucket { // The bucket instance is only valid for the lifetime of the transaction. func (b *Bucket) CreateBucket(key []byte) (*Bucket, error) { if b.tx.db == nil { - return nil, common.ErrTxClosed + return nil, errors.ErrTxClosed } else if !b.tx.writable { - return nil, common.ErrTxNotWritable + return nil, errors.ErrTxNotWritable } else if len(key) == 0 { - return nil, common.ErrBucketNameRequired + return nil, errors.ErrBucketNameRequired } // Move cursor to correct position. @@ -160,9 +161,9 @@ func (b *Bucket) CreateBucket(key []byte) (*Bucket, error) { // Return an error if there is an existing key. if bytes.Equal(key, k) { if (flags & common.BucketLeafFlag) != 0 { - return nil, common.ErrBucketExists + return nil, errors.ErrBucketExists } - return nil, common.ErrIncompatibleValue + return nil, errors.ErrIncompatibleValue } // Create empty, inline bucket. @@ -190,7 +191,7 @@ func (b *Bucket) CreateBucket(key []byte) (*Bucket, error) { // The bucket instance is only valid for the lifetime of the transaction. func (b *Bucket) CreateBucketIfNotExists(key []byte) (*Bucket, error) { child, err := b.CreateBucket(key) - if err == common.ErrBucketExists { + if err == errors.ErrBucketExists { return b.Bucket(key), nil } else if err != nil { return nil, err @@ -202,9 +203,9 @@ func (b *Bucket) CreateBucketIfNotExists(key []byte) (*Bucket, error) { // Returns an error if the bucket does not exist, or if the key represents a non-bucket value. func (b *Bucket) DeleteBucket(key []byte) error { if b.tx.db == nil { - return common.ErrTxClosed + return errors.ErrTxClosed } else if !b.Writable() { - return common.ErrTxNotWritable + return errors.ErrTxNotWritable } // Move cursor to correct position. @@ -213,9 +214,9 @@ func (b *Bucket) DeleteBucket(key []byte) error { // Return an error if bucket doesn't exist or is not a bucket. if !bytes.Equal(key, k) { - return common.ErrBucketNotFound + return errors.ErrBucketNotFound } else if (flags & common.BucketLeafFlag) == 0 { - return common.ErrIncompatibleValue + return errors.ErrIncompatibleValue } // Recursively delete all child buckets. @@ -268,15 +269,15 @@ func (b *Bucket) Get(key []byte) []byte { // Returns an error if the bucket was created from a read-only transaction, if the key is blank, if the key is too large, or if the value is too large. func (b *Bucket) Put(key []byte, value []byte) error { if b.tx.db == nil { - return common.ErrTxClosed + return errors.ErrTxClosed } else if !b.Writable() { - return common.ErrTxNotWritable + return errors.ErrTxNotWritable } else if len(key) == 0 { - return common.ErrKeyRequired + return errors.ErrKeyRequired } else if len(key) > MaxKeySize { - return common.ErrKeyTooLarge + return errors.ErrKeyTooLarge } else if int64(len(value)) > MaxValueSize { - return common.ErrValueTooLarge + return errors.ErrValueTooLarge } // Move cursor to correct position. @@ -285,7 +286,7 @@ func (b *Bucket) Put(key []byte, value []byte) error { // Return an error if there is an existing key with a bucket value. if bytes.Equal(key, k) && (flags&common.BucketLeafFlag) != 0 { - return common.ErrIncompatibleValue + return errors.ErrIncompatibleValue } // Insert into node. @@ -300,9 +301,9 @@ func (b *Bucket) Put(key []byte, value []byte) error { // Returns an error if the bucket was created from a read-only transaction. func (b *Bucket) Delete(key []byte) error { if b.tx.db == nil { - return common.ErrTxClosed + return errors.ErrTxClosed } else if !b.Writable() { - return common.ErrTxNotWritable + return errors.ErrTxNotWritable } // Move cursor to correct position. @@ -316,7 +317,7 @@ func (b *Bucket) Delete(key []byte) error { // Return an error if there is already existing bucket value. if (flags & common.BucketLeafFlag) != 0 { - return common.ErrIncompatibleValue + return errors.ErrIncompatibleValue } // Delete the node if we have a matching key. @@ -333,9 +334,9 @@ func (b *Bucket) Sequence() uint64 { // SetSequence updates the sequence number for the bucket. func (b *Bucket) SetSequence(v uint64) error { if b.tx.db == nil { - return common.ErrTxClosed + return errors.ErrTxClosed } else if !b.Writable() { - return common.ErrTxNotWritable + return errors.ErrTxNotWritable } // Materialize the root node if it hasn't been already so that the @@ -352,9 +353,9 @@ func (b *Bucket) SetSequence(v uint64) error { // NextSequence returns an autoincrementing integer for the bucket. func (b *Bucket) NextSequence() (uint64, error) { if b.tx.db == nil { - return 0, common.ErrTxClosed + return 0, errors.ErrTxClosed } else if !b.Writable() { - return 0, common.ErrTxNotWritable + return 0, errors.ErrTxNotWritable } // Materialize the root node if it hasn't been already so that the @@ -375,7 +376,7 @@ func (b *Bucket) NextSequence() (uint64, error) { // the bucket; this will result in undefined behavior. func (b *Bucket) ForEach(fn func(k, v []byte) error) error { if b.tx.db == nil { - return common.ErrTxClosed + return errors.ErrTxClosed } c := b.Cursor() for k, v := c.First(); k != nil; k, v = c.Next() { @@ -388,7 +389,7 @@ func (b *Bucket) ForEach(fn func(k, v []byte) error) error { func (b *Bucket) ForEachBucket(fn func(k []byte) error) error { if b.tx.db == nil { - return common.ErrTxClosed + return errors.ErrTxClosed } c := b.Cursor() for k, _, flags := c.first(); k != nil; k, _, flags = c.next() { diff --git a/bucket_test.go b/bucket_test.go index 33ff149..595631a 100644 --- a/bucket_test.go +++ b/bucket_test.go @@ -17,8 +17,8 @@ import ( "github.com/stretchr/testify/require" bolt "go.etcd.io/bbolt" + berrors "go.etcd.io/bbolt/errors" "go.etcd.io/bbolt/internal/btesting" - "go.etcd.io/bbolt/internal/common" ) // Ensure that a bucket that gets a non-existent key returns nil. @@ -247,7 +247,7 @@ func TestBucket_Put_IncompatibleValue(t *testing.T) { if _, err := tx.Bucket([]byte("widgets")).CreateBucket([]byte("foo")); err != nil { t.Fatal(err) } - if err := b0.Put([]byte("foo"), []byte("bar")); err != common.ErrIncompatibleValue { + if err := b0.Put([]byte("foo"), []byte("bar")); err != berrors.ErrIncompatibleValue { t.Fatalf("unexpected error: %s", err) } return nil @@ -273,7 +273,7 @@ func TestBucket_Put_Closed(t *testing.T) { t.Fatal(err) } - if err := b.Put([]byte("foo"), []byte("bar")); err != common.ErrTxClosed { + if err := b.Put([]byte("foo"), []byte("bar")); err != berrors.ErrTxClosed { t.Fatalf("unexpected error: %s", err) } } @@ -293,7 +293,7 @@ func TestBucket_Put_ReadOnly(t *testing.T) { if err := db.View(func(tx *bolt.Tx) error { b := tx.Bucket([]byte("widgets")) - if err := b.Put([]byte("foo"), []byte("bar")); err != common.ErrTxNotWritable { + if err := b.Put([]byte("foo"), []byte("bar")); err != berrors.ErrTxNotWritable { t.Fatalf("unexpected error: %s", err) } return nil @@ -561,7 +561,7 @@ func TestBucket_Delete_Bucket(t *testing.T) { if _, err := b.CreateBucket([]byte("foo")); err != nil { t.Fatal(err) } - if err := b.Delete([]byte("foo")); err != common.ErrIncompatibleValue { + if err := b.Delete([]byte("foo")); err != berrors.ErrIncompatibleValue { t.Fatalf("unexpected error: %s", err) } return nil @@ -584,7 +584,7 @@ func TestBucket_Delete_ReadOnly(t *testing.T) { } if err := db.View(func(tx *bolt.Tx) error { - if err := tx.Bucket([]byte("widgets")).Delete([]byte("foo")); err != common.ErrTxNotWritable { + if err := tx.Bucket([]byte("widgets")).Delete([]byte("foo")); err != berrors.ErrTxNotWritable { t.Fatalf("unexpected error: %s", err) } return nil @@ -610,7 +610,7 @@ func TestBucket_Delete_Closed(t *testing.T) { if err := tx.Rollback(); err != nil { t.Fatal(err) } - if err := b.Delete([]byte("foo")); err != common.ErrTxClosed { + if err := b.Delete([]byte("foo")); err != berrors.ErrTxClosed { t.Fatalf("unexpected error: %s", err) } } @@ -781,7 +781,7 @@ func TestBucket_CreateBucket_IncompatibleValue(t *testing.T) { if err := widgets.Put([]byte("foo"), []byte("bar")); err != nil { t.Fatal(err) } - if _, err := widgets.CreateBucket([]byte("foo")); err != common.ErrIncompatibleValue { + if _, err := widgets.CreateBucket([]byte("foo")); err != berrors.ErrIncompatibleValue { t.Fatalf("unexpected error: %s", err) } return nil @@ -802,7 +802,7 @@ func TestBucket_DeleteBucket_IncompatibleValue(t *testing.T) { if err := widgets.Put([]byte("foo"), []byte("bar")); err != nil { t.Fatal(err) } - if err := tx.Bucket([]byte("widgets")).DeleteBucket([]byte("foo")); err != common.ErrIncompatibleValue { + if err := tx.Bucket([]byte("widgets")).DeleteBucket([]byte("foo")); err != berrors.ErrIncompatibleValue { t.Fatalf("unexpected error: %s", err) } return nil @@ -944,7 +944,7 @@ func TestBucket_NextSequence_ReadOnly(t *testing.T) { if err := db.View(func(tx *bolt.Tx) error { _, err := tx.Bucket([]byte("widgets")).NextSequence() - if err != common.ErrTxNotWritable { + if err != berrors.ErrTxNotWritable { t.Fatalf("unexpected error: %s", err) } return nil @@ -967,7 +967,7 @@ func TestBucket_NextSequence_Closed(t *testing.T) { if err := tx.Rollback(); err != nil { t.Fatal(err) } - if _, err := b.NextSequence(); err != common.ErrTxClosed { + if _, err := b.NextSequence(); err != berrors.ErrTxClosed { t.Fatal(err) } } @@ -1159,7 +1159,7 @@ func TestBucket_ForEach_Closed(t *testing.T) { t.Fatal(err) } - if err := b.ForEach(func(k, v []byte) error { return nil }); err != common.ErrTxClosed { + if err := b.ForEach(func(k, v []byte) error { return nil }); err != berrors.ErrTxClosed { t.Fatalf("unexpected error: %s", err) } } @@ -1173,10 +1173,10 @@ func TestBucket_Put_EmptyKey(t *testing.T) { if err != nil { t.Fatal(err) } - if err := b.Put([]byte(""), []byte("bar")); err != common.ErrKeyRequired { + if err := b.Put([]byte(""), []byte("bar")); err != berrors.ErrKeyRequired { t.Fatalf("unexpected error: %s", err) } - if err := b.Put(nil, []byte("bar")); err != common.ErrKeyRequired { + if err := b.Put(nil, []byte("bar")); err != berrors.ErrKeyRequired { t.Fatalf("unexpected error: %s", err) } return nil @@ -1193,7 +1193,7 @@ func TestBucket_Put_KeyTooLarge(t *testing.T) { if err != nil { t.Fatal(err) } - if err := b.Put(make([]byte, 32769), []byte("bar")); err != common.ErrKeyTooLarge { + if err := b.Put(make([]byte, 32769), []byte("bar")); err != berrors.ErrKeyTooLarge { t.Fatalf("unexpected error: %s", err) } return nil @@ -1216,7 +1216,7 @@ func TestBucket_Put_ValueTooLarge(t *testing.T) { if err != nil { t.Fatal(err) } - if err := b.Put([]byte("foo"), make([]byte, bolt.MaxValueSize+1)); err != common.ErrValueTooLarge { + if err := b.Put([]byte("foo"), make([]byte, bolt.MaxValueSize+1)); err != berrors.ErrValueTooLarge { t.Fatalf("unexpected error: %s", err) } return nil diff --git a/cmd/bbolt/main.go b/cmd/bbolt/main.go index 413a49a..31d0d62 100644 --- a/cmd/bbolt/main.go +++ b/cmd/bbolt/main.go @@ -21,6 +21,7 @@ import ( "unicode/utf8" bolt "go.etcd.io/bbolt" + berrors "go.etcd.io/bbolt/errors" "go.etcd.io/bbolt/internal/common" "go.etcd.io/bbolt/internal/guts_cli" ) @@ -941,12 +942,12 @@ func (cmd *keysCommand) Run(args ...string) error { // Find bucket. var lastbucket *bolt.Bucket = tx.Bucket([]byte(buckets[0])) if lastbucket == nil { - return common.ErrBucketNotFound + return berrors.ErrBucketNotFound } for _, bucket := range buckets[1:] { lastbucket = lastbucket.Bucket([]byte(bucket)) if lastbucket == nil { - return common.ErrBucketNotFound + return berrors.ErrBucketNotFound } } @@ -1017,7 +1018,7 @@ func (cmd *getCommand) Run(args ...string) error { } else if len(buckets) == 0 { return ErrBucketRequired } else if len(key) == 0 { - return common.ErrKeyRequired + return berrors.ErrKeyRequired } // Open database. @@ -1032,12 +1033,12 @@ func (cmd *getCommand) Run(args ...string) error { // Find bucket. var lastbucket *bolt.Bucket = tx.Bucket([]byte(buckets[0])) if lastbucket == nil { - return common.ErrBucketNotFound + return berrors.ErrBucketNotFound } for _, bucket := range buckets[1:] { lastbucket = lastbucket.Bucket([]byte(bucket)) if lastbucket == nil { - return common.ErrBucketNotFound + return berrors.ErrBucketNotFound } } diff --git a/cursor.go b/cursor.go index 14556e5..acd2216 100644 --- a/cursor.go +++ b/cursor.go @@ -5,6 +5,7 @@ import ( "fmt" "sort" + "go.etcd.io/bbolt/errors" "go.etcd.io/bbolt/internal/common" ) @@ -138,15 +139,15 @@ func (c *Cursor) Seek(seek []byte) (key []byte, value []byte) { // Delete fails if current key/value is a bucket or if the transaction is not writable. func (c *Cursor) Delete() error { if c.bucket.tx.db == nil { - return common.ErrTxClosed + return errors.ErrTxClosed } else if !c.bucket.Writable() { - return common.ErrTxNotWritable + return errors.ErrTxNotWritable } key, _, flags := c.keyValue() // Return an error if current value is a bucket. if (flags & common.BucketLeafFlag) != 0 { - return common.ErrIncompatibleValue + return errors.ErrIncompatibleValue } c.node().del(key) diff --git a/cursor_test.go b/cursor_test.go index 8fff82e..20e6614 100644 --- a/cursor_test.go +++ b/cursor_test.go @@ -12,8 +12,8 @@ import ( "testing/quick" bolt "go.etcd.io/bbolt" + "go.etcd.io/bbolt/errors" "go.etcd.io/bbolt/internal/btesting" - "go.etcd.io/bbolt/internal/common" ) // Ensure that a cursor can return a reference to the bucket that created it. @@ -140,7 +140,7 @@ func TestCursor_Delete(t *testing.T) { } c.Seek([]byte("sub")) - if err := c.Delete(); err != common.ErrIncompatibleValue { + if err := c.Delete(); err != errors.ErrIncompatibleValue { t.Fatalf("unexpected error: %s", err) } diff --git a/db.go b/db.go index 0e364e1..d17322d 100644 --- a/db.go +++ b/db.go @@ -11,6 +11,7 @@ import ( "time" "unsafe" + berrors "go.etcd.io/bbolt/errors" "go.etcd.io/bbolt/internal/common" ) @@ -233,7 +234,7 @@ func Open(path string, mode os.FileMode, options *Options) (*DB, error) { db.pageSize = pgSize } else { _ = db.close() - return nil, common.ErrInvalid + return nil, berrors.ErrInvalid } } @@ -311,7 +312,7 @@ func (db *DB) getPageSize() (int, error) { return db.pageSize, nil } - return 0, common.ErrInvalid + return 0, berrors.ErrInvalid } // getPageSizeFromFirstMeta reads the pageSize from the first meta page @@ -324,7 +325,7 @@ func (db *DB) getPageSizeFromFirstMeta() (int, bool, error) { return int(m.PageSize()), metaCanRead, nil } } - return 0, metaCanRead, common.ErrInvalid + return 0, metaCanRead, berrors.ErrInvalid } // getPageSizeFromSecondMeta reads the pageSize from the second meta page @@ -362,7 +363,7 @@ func (db *DB) getPageSizeFromSecondMeta() (int, bool, error) { } } - return 0, metaCanRead, common.ErrInvalid + return 0, metaCanRead, berrors.ErrInvalid } // loadFreelist reads the freelist if it is synced, or reconstructs it @@ -697,14 +698,14 @@ func (db *DB) beginTx() (*Tx, error) { if !db.opened { db.mmaplock.RUnlock() db.metalock.Unlock() - return nil, common.ErrDatabaseNotOpen + return nil, berrors.ErrDatabaseNotOpen } // Exit if the database is not correctly mapped. if db.data == nil { db.mmaplock.RUnlock() db.metalock.Unlock() - return nil, common.ErrInvalidMapping + return nil, berrors.ErrInvalidMapping } // Create a transaction associated with the database. @@ -730,7 +731,7 @@ func (db *DB) beginTx() (*Tx, error) { func (db *DB) beginRWTx() (*Tx, error) { // If the database was opened with Options.ReadOnly, return an error. if db.readOnly { - return nil, common.ErrDatabaseReadOnly + return nil, berrors.ErrDatabaseReadOnly } // Obtain writer lock. This is released by the transaction when it closes. @@ -745,13 +746,13 @@ func (db *DB) beginRWTx() (*Tx, error) { // Exit if the database is not open yet. if !db.opened { db.rwlock.Unlock() - return nil, common.ErrDatabaseNotOpen + return nil, berrors.ErrDatabaseNotOpen } // Exit if the database is not correctly mapped. if db.data == nil { db.rwlock.Unlock() - return nil, common.ErrInvalidMapping + return nil, berrors.ErrInvalidMapping } // Create a transaction associated with the database. diff --git a/db_test.go b/db_test.go index a92782c..153de47 100644 --- a/db_test.go +++ b/db_test.go @@ -20,8 +20,8 @@ import ( "github.com/stretchr/testify/require" bolt "go.etcd.io/bbolt" + berrors "go.etcd.io/bbolt/errors" "go.etcd.io/bbolt/internal/btesting" - "go.etcd.io/bbolt/internal/common" ) // pageSize is the size of one page in the data file. @@ -137,7 +137,7 @@ func TestOpen_ErrInvalid(t *testing.T) { t.Fatal(err) } - if _, err := bolt.Open(path, 0666, nil); err != common.ErrInvalid { + if _, err := bolt.Open(path, 0666, nil); err != berrors.ErrInvalid { t.Fatalf("unexpected error: %s", err) } } @@ -173,7 +173,7 @@ func TestOpen_ErrVersionMismatch(t *testing.T) { } // Reopen data file. - if _, err := bolt.Open(path, 0666, nil); err != common.ErrVersionMismatch { + if _, err := bolt.Open(path, 0666, nil); err != berrors.ErrVersionMismatch { t.Fatalf("unexpected error: %s", err) } } @@ -209,7 +209,7 @@ func TestOpen_ErrChecksum(t *testing.T) { } // Reopen data file. - if _, err := bolt.Open(path, 0666, nil); err != common.ErrChecksum { + if _, err := bolt.Open(path, 0666, nil); err != berrors.ErrChecksum { t.Fatalf("unexpected error: %s", err) } } @@ -553,7 +553,7 @@ func TestDB_Open_ReadOnly(t *testing.T) { } // Can't launch read-write transaction. - if _, err := readOnlyDB.Begin(true); err != common.ErrDatabaseReadOnly { + if _, err := readOnlyDB.Begin(true); err != berrors.ErrDatabaseReadOnly { t.Fatalf("unexpected error: %s", err) } @@ -642,7 +642,7 @@ func TestOpen_RecoverFreeList(t *testing.T) { // Ensure that a database cannot open a transaction when it's not open. func TestDB_Begin_ErrDatabaseNotOpen(t *testing.T) { var db bolt.DB - if _, err := db.Begin(false); err != common.ErrDatabaseNotOpen { + if _, err := db.Begin(false); err != berrors.ErrDatabaseNotOpen { t.Fatalf("unexpected error: %s", err) } } @@ -728,7 +728,7 @@ func TestDB_Concurrent_WriteTo(t *testing.T) { // Ensure that opening a transaction while the DB is closed returns an error. func TestDB_BeginRW_Closed(t *testing.T) { var db bolt.DB - if _, err := db.Begin(true); err != common.ErrDatabaseNotOpen { + if _, err := db.Begin(true); err != berrors.ErrDatabaseNotOpen { t.Fatalf("unexpected error: %s", err) } } @@ -832,7 +832,7 @@ func TestDB_Update_Closed(t *testing.T) { t.Fatal(err) } return nil - }); err != common.ErrDatabaseNotOpen { + }); err != berrors.ErrDatabaseNotOpen { t.Fatalf("unexpected error: %s", err) } } diff --git a/db_whitebox_test.go b/db_whitebox_test.go index 8b195f7..130c3e3 100644 --- a/db_whitebox_test.go +++ b/db_whitebox_test.go @@ -7,7 +7,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "go.etcd.io/bbolt/internal/common" + "go.etcd.io/bbolt/errors" ) func TestOpenWithPreLoadFreelist(t *testing.T) { @@ -78,7 +78,7 @@ func TestMethodPage(t *testing.T) { name: "readonly mode without preloading free pages", readonly: true, preLoadFreePage: false, - expectedError: common.ErrFreePagesNotLoaded, + expectedError: errors.ErrFreePagesNotLoaded, }, } diff --git a/errors.go b/errors.go new file mode 100644 index 0000000..28ca48d --- /dev/null +++ b/errors.go @@ -0,0 +1,114 @@ +package bbolt + +import "go.etcd.io/bbolt/errors" + +// These errors can be returned when opening or calling methods on a DB. +var ( + // ErrDatabaseNotOpen is returned when a DB instance is accessed before it + // is opened or after it is closed. + // + // Deprecated: Use the error variables defined in the bbolt/errors package. + ErrDatabaseNotOpen = errors.ErrDatabaseNotOpen + + // ErrDatabaseOpen is returned when opening a database that is + // already open. + // + // Deprecated: Use the error variables defined in the bbolt/errors package. + ErrDatabaseOpen = errors.ErrDatabaseOpen + + // ErrInvalid is returned when both meta pages on a database are invalid. + // This typically occurs when a file is not a bolt database. + // + // Deprecated: Use the error variables defined in the bbolt/errors package. + ErrInvalid = errors.ErrInvalid + + // ErrInvalidMapping is returned when the database file fails to get mapped. + // + // Deprecated: Use the error variables defined in the bbolt/errors package. + ErrInvalidMapping = errors.ErrInvalidMapping + + // ErrVersionMismatch is returned when the data file was created with a + // different version of Bolt. + // + // Deprecated: Use the error variables defined in the bbolt/errors package. + ErrVersionMismatch = errors.ErrVersionMismatch + + // ErrChecksum is returned when either meta page checksum does not match. + // + // Deprecated: Use the error variables defined in the bbolt/errors package. + ErrChecksum = errors.ErrChecksum + + // ErrTimeout is returned when a database cannot obtain an exclusive lock + // on the data file after the timeout passed to Open(). + // + // Deprecated: Use the error variables defined in the bbolt/errors package. + ErrTimeout = errors.ErrTimeout +) + +// These errors can occur when beginning or committing a Tx. +var ( + // ErrTxNotWritable is returned when performing a write operation on a + // read-only transaction. + // + // Deprecated: Use the error variables defined in the bbolt/errors package. + ErrTxNotWritable = errors.ErrTxNotWritable + + // ErrTxClosed is returned when committing or rolling back a transaction + // that has already been committed or rolled back. + // + // Deprecated: Use the error variables defined in the bbolt/errors package. + ErrTxClosed = errors.ErrTxClosed + + // ErrDatabaseReadOnly is returned when a mutating transaction is started on a + // read-only database. + // + // Deprecated: Use the error variables defined in the bbolt/errors package. + ErrDatabaseReadOnly = errors.ErrDatabaseReadOnly + + // ErrFreePagesNotLoaded is returned when a readonly transaction without + // preloading the free pages is trying to access the free pages. + // + // Deprecated: Use the error variables defined in the bbolt/errors package. + ErrFreePagesNotLoaded = errors.ErrFreePagesNotLoaded +) + +// These errors can occur when putting or deleting a value or a bucket. +var ( + // ErrBucketNotFound is returned when trying to access a bucket that has + // not been created yet. + // + // Deprecated: Use the error variables defined in the bbolt/errors package. + ErrBucketNotFound = errors.ErrBucketNotFound + + // ErrBucketExists is returned when creating a bucket that already exists. + // + // Deprecated: Use the error variables defined in the bbolt/errors package. + ErrBucketExists = errors.ErrBucketExists + + // ErrBucketNameRequired is returned when creating a bucket with a blank name. + // + // Deprecated: Use the error variables defined in the bbolt/errors package. + ErrBucketNameRequired = errors.ErrBucketNameRequired + + // ErrKeyRequired is returned when inserting a zero-length key. + // + // Deprecated: Use the error variables defined in the bbolt/errors package. + ErrKeyRequired = errors.ErrKeyRequired + + // ErrKeyTooLarge is returned when inserting a key that is larger than MaxKeySize. + // + // Deprecated: Use the error variables defined in the bbolt/errors package. + ErrKeyTooLarge = errors.ErrKeyTooLarge + + // ErrValueTooLarge is returned when inserting a value that is larger than MaxValueSize. + // + // Deprecated: Use the error variables defined in the bbolt/errors package. + ErrValueTooLarge = errors.ErrValueTooLarge + + // ErrIncompatibleValue is returned when trying 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. + // + // Deprecated: Use the error variables defined in the bbolt/errors package. + ErrIncompatibleValue = errors.ErrIncompatibleValue +) diff --git a/internal/common/errors.go b/errors/errors.go similarity index 96% rename from internal/common/errors.go rename to errors/errors.go index fd1d354..88fdc31 100644 --- a/internal/common/errors.go +++ b/errors/errors.go @@ -1,4 +1,6 @@ -package common +// Package errors defines the error variables that may be returned +// during bbolt operations. +package errors import "errors" diff --git a/internal/common/meta.go b/internal/common/meta.go index 7769ccc..79727c8 100644 --- a/internal/common/meta.go +++ b/internal/common/meta.go @@ -5,6 +5,8 @@ import ( "hash/fnv" "io" "unsafe" + + "go.etcd.io/bbolt/errors" ) type Meta struct { @@ -22,11 +24,11 @@ type Meta struct { // Validate checks the marker bytes and version of the meta page to ensure it matches this binary. func (m *Meta) Validate() error { if m.magic != Magic { - return ErrInvalid + return errors.ErrInvalid } else if m.version != Version { - return ErrVersionMismatch + return errors.ErrVersionMismatch } else if m.checksum != m.Sum64() { - return ErrChecksum + return errors.ErrChecksum } return nil } diff --git a/tx.go b/tx.go index 67362b6..340dda8 100644 --- a/tx.go +++ b/tx.go @@ -10,6 +10,7 @@ import ( "time" "unsafe" + "go.etcd.io/bbolt/errors" "go.etcd.io/bbolt/internal/common" ) @@ -141,9 +142,9 @@ func (tx *Tx) OnCommit(fn func()) { func (tx *Tx) Commit() error { common.Assert(!tx.managed, "managed tx commit not allowed") if tx.db == nil { - return common.ErrTxClosed + return errors.ErrTxClosed } else if !tx.writable { - return common.ErrTxNotWritable + return errors.ErrTxNotWritable } // TODO(benbjohnson): Use vectorized I/O to write out dirty pages. @@ -253,7 +254,7 @@ func (tx *Tx) commitFreelist() error { func (tx *Tx) Rollback() error { common.Assert(!tx.managed, "managed tx rollback not allowed") if tx.db == nil { - return common.ErrTxClosed + return errors.ErrTxClosed } tx.nonPhysicalRollback() return nil @@ -560,13 +561,13 @@ func (tx *Tx) forEachPageInternal(pgidstack []common.Pgid, fn func(*common.Page, // This is only safe for concurrent use when used by a writable transaction. func (tx *Tx) Page(id int) (*common.PageInfo, error) { if tx.db == nil { - return nil, common.ErrTxClosed + return nil, errors.ErrTxClosed } else if common.Pgid(id) >= tx.meta.Pgid() { return nil, nil } if tx.db.freelist == nil { - return nil, common.ErrFreePagesNotLoaded + return nil, errors.ErrFreePagesNotLoaded } // Build the page info. diff --git a/tx_test.go b/tx_test.go index 44cbbf1..ceda344 100644 --- a/tx_test.go +++ b/tx_test.go @@ -14,8 +14,8 @@ import ( "github.com/stretchr/testify/require" bolt "go.etcd.io/bbolt" + berrors "go.etcd.io/bbolt/errors" "go.etcd.io/bbolt/internal/btesting" - "go.etcd.io/bbolt/internal/common" ) // TestTx_Check_ReadOnly tests consistency checking on a ReadOnly database. @@ -85,7 +85,7 @@ func TestTx_Commit_ErrTxClosed(t *testing.T) { t.Fatal(err) } - if err := tx.Commit(); err != common.ErrTxClosed { + if err := tx.Commit(); err != berrors.ErrTxClosed { t.Fatalf("unexpected error: %s", err) } } @@ -102,7 +102,7 @@ func TestTx_Rollback_ErrTxClosed(t *testing.T) { if err := tx.Rollback(); err != nil { t.Fatal(err) } - if err := tx.Rollback(); err != common.ErrTxClosed { + if err := tx.Rollback(); err != berrors.ErrTxClosed { t.Fatalf("unexpected error: %s", err) } } @@ -114,7 +114,7 @@ func TestTx_Commit_ErrTxNotWritable(t *testing.T) { if err != nil { t.Fatal(err) } - if err := tx.Commit(); err != common.ErrTxNotWritable { + if err := tx.Commit(); err != berrors.ErrTxNotWritable { t.Fatal(err) } // Close the view transaction @@ -166,7 +166,7 @@ func TestTx_CreateBucket_ErrTxNotWritable(t *testing.T) { db := btesting.MustCreateDB(t) if err := db.View(func(tx *bolt.Tx) error { _, err := tx.CreateBucket([]byte("foo")) - if err != common.ErrTxNotWritable { + if err != berrors.ErrTxNotWritable { t.Fatalf("unexpected error: %s", err) } return nil @@ -186,7 +186,7 @@ func TestTx_CreateBucket_ErrTxClosed(t *testing.T) { t.Fatal(err) } - if _, err := tx.CreateBucket([]byte("foo")); err != common.ErrTxClosed { + if _, err := tx.CreateBucket([]byte("foo")); err != berrors.ErrTxClosed { t.Fatalf("unexpected error: %s", err) } } @@ -294,11 +294,11 @@ func TestTx_CreateBucketIfNotExists(t *testing.T) { func TestTx_CreateBucketIfNotExists_ErrBucketNameRequired(t *testing.T) { db := btesting.MustCreateDB(t) if err := db.Update(func(tx *bolt.Tx) error { - if _, err := tx.CreateBucketIfNotExists([]byte{}); err != common.ErrBucketNameRequired { + if _, err := tx.CreateBucketIfNotExists([]byte{}); err != berrors.ErrBucketNameRequired { t.Fatalf("unexpected error: %s", err) } - if _, err := tx.CreateBucketIfNotExists(nil); err != common.ErrBucketNameRequired { + if _, err := tx.CreateBucketIfNotExists(nil); err != berrors.ErrBucketNameRequired { t.Fatalf("unexpected error: %s", err) } @@ -324,7 +324,7 @@ func TestTx_CreateBucket_ErrBucketExists(t *testing.T) { // Create the same bucket again. if err := db.Update(func(tx *bolt.Tx) error { - if _, err := tx.CreateBucket([]byte("widgets")); err != common.ErrBucketExists { + if _, err := tx.CreateBucket([]byte("widgets")); err != berrors.ErrBucketExists { t.Fatalf("unexpected error: %s", err) } return nil @@ -337,7 +337,7 @@ func TestTx_CreateBucket_ErrBucketExists(t *testing.T) { func TestTx_CreateBucket_ErrBucketNameRequired(t *testing.T) { db := btesting.MustCreateDB(t) if err := db.Update(func(tx *bolt.Tx) error { - if _, err := tx.CreateBucket(nil); err != common.ErrBucketNameRequired { + if _, err := tx.CreateBucket(nil); err != berrors.ErrBucketNameRequired { t.Fatalf("unexpected error: %s", err) } return nil @@ -402,7 +402,7 @@ func TestTx_DeleteBucket_ErrTxClosed(t *testing.T) { if err := tx.Commit(); err != nil { t.Fatal(err) } - if err := tx.DeleteBucket([]byte("foo")); err != common.ErrTxClosed { + if err := tx.DeleteBucket([]byte("foo")); err != berrors.ErrTxClosed { t.Fatalf("unexpected error: %s", err) } } @@ -411,7 +411,7 @@ func TestTx_DeleteBucket_ErrTxClosed(t *testing.T) { func TestTx_DeleteBucket_ReadOnly(t *testing.T) { db := btesting.MustCreateDB(t) if err := db.View(func(tx *bolt.Tx) error { - if err := tx.DeleteBucket([]byte("foo")); err != common.ErrTxNotWritable { + if err := tx.DeleteBucket([]byte("foo")); err != berrors.ErrTxNotWritable { t.Fatalf("unexpected error: %s", err) } return nil @@ -424,7 +424,7 @@ func TestTx_DeleteBucket_ReadOnly(t *testing.T) { func TestTx_DeleteBucket_NotFound(t *testing.T) { db := btesting.MustCreateDB(t) if err := db.Update(func(tx *bolt.Tx) error { - if err := tx.DeleteBucket([]byte("widgets")); err != common.ErrBucketNotFound { + if err := tx.DeleteBucket([]byte("widgets")); err != berrors.ErrBucketNotFound { t.Fatalf("unexpected error: %s", err) } return nil