diff options
Diffstat (limited to 'bucket.go')
-rw-r--r-- | bucket.go | 111 |
1 files changed, 104 insertions, 7 deletions
@@ -1,13 +1,15 @@ package bolt +import ( + "bytes" +) + // Bucket represents a collection of key/value pairs inside the database. -// All keys inside the bucket are unique. The Bucket type is not typically used -// directly. Instead the bucket name is typically passed into the Get(), Put(), -// or Delete() functions. type Bucket struct { *bucket - name string - transaction *Transaction + name string + transaction *Transaction + rwtransaction *RWTransaction } // bucket represents the on-file representation of a bucket. @@ -21,8 +23,15 @@ func (b *Bucket) Name() string { return b.name } -// cursor creates a new cursor for this bucket. -func (b *Bucket) cursor() *Cursor { +// Writable returns whether the bucket is writable. +func (b *Bucket) Writable() bool { + return (b.rwtransaction != nil) +} + +// Cursor creates a cursor associated with the bucket. +// The cursor is only valid as long as the Transaction is open. +// Do not use a cursor after the transaction is closed. +func (b *Bucket) Cursor() *Cursor { return &Cursor{ transaction: b.transaction, root: b.root, @@ -30,6 +39,94 @@ func (b *Bucket) cursor() *Cursor { } } +// Get retrieves the value for a key in the bucket. +// Returns a nil value if the key does not exist. +func (b *Bucket) Get(key []byte) []byte { + c := b.Cursor() + k, v := c.Seek(key) + + // If our target node isn't the same key as what's passed in then return nil. + if !bytes.Equal(key, k) { + return nil + } + return v +} + +// Put sets the value for a key in the bucket. +// If the key exist then its previous value will be overwritten. +// 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.Writable() { + return ErrBucketNotWritable + } + + // Validate the key and data size. + if len(key) == 0 { + return ErrKeyRequired + } else if len(key) > MaxKeySize { + return ErrKeyTooLarge + } else if len(value) > MaxValueSize { + return ErrValueTooLarge + } + + // Move cursor to correct position. + c := b.Cursor() + c.Seek(key) + + // Insert the key/value. + c.node(b.rwtransaction).put(key, key, value, 0) + + return nil +} + +// Delete removes a key from the bucket. +// If the key does not exist then nothing is done and a nil error is returned. +// Returns an error if the bucket was created from a read-only transaction. +func (b *Bucket) Delete(key []byte) error { + if !b.Writable() { + return ErrBucketNotWritable + } + + // Move cursor to correct position. + c := b.Cursor() + c.Seek(key) + + // Delete the node if we have a matching key. + c.node(b.rwtransaction).del(key) + + return nil +} + +// NextSequence returns an autoincrementing integer for the bucket. +func (b *Bucket) NextSequence() (int, error) { + if !b.Writable() { + return 0, ErrBucketNotWritable + } + + // Make sure next sequence number will not be larger than the maximum + // integer size of the system. + if b.bucket.sequence == uint64(maxInt) { + return 0, ErrSequenceOverflow + } + + // Increment and return the sequence. + b.bucket.sequence++ + + return int(b.bucket.sequence), nil +} + +// ForEach executes a function for each key/value pair in a bucket. +// An error is returned if the bucket cannot be found. +func (b *Bucket) ForEach(fn func(k, v []byte) error) error { + c := b.Cursor() + for k, v := c.First(); k != nil; k, v = c.Next() { + if err := fn(k, v); err != nil { + return err + } + } + return nil +} + // Stat returns stats on a bucket. func (b *Bucket) Stat() *BucketStat { s := &BucketStat{} |