2014-01-08 15:06:17 +00:00
package bolt
2014-02-23 06:08:30 +00:00
import (
"bytes"
)
2014-02-12 21:57:27 +00:00
// Bucket represents a collection of key/value pairs inside the database.
2014-01-10 14:32:12 +00:00
type Bucket struct {
2014-01-14 20:01:02 +00:00
* bucket
2014-03-09 00:01:49 +00:00
name string
tx * Tx
2014-01-14 20:01:02 +00:00
}
2014-02-12 21:57:27 +00:00
// bucket represents the on-file representation of a bucket.
2014-01-14 20:01:02 +00:00
type bucket struct {
2014-02-16 04:50:34 +00:00
root pgid
2014-02-15 17:23:00 +00:00
sequence uint64
2014-01-08 15:06:17 +00:00
}
2014-01-26 22:29:06 +00:00
2014-01-30 05:11:46 +00:00
// Name returns the name of the bucket.
func ( b * Bucket ) Name ( ) string {
return b . name
}
2014-02-23 06:08:30 +00:00
// Writable returns whether the bucket is writable.
func ( b * Bucket ) Writable ( ) bool {
2014-03-09 03:25:37 +00:00
return b . tx . writable
2014-02-23 06:08:30 +00:00
}
// Cursor creates a cursor associated with the bucket.
2014-03-09 00:01:49 +00:00
// The cursor is only valid as long as the transaction is open.
2014-02-23 06:08:30 +00:00
// Do not use a cursor after the transaction is closed.
func ( b * Bucket ) Cursor ( ) * Cursor {
2014-01-27 15:11:54 +00:00
return & Cursor {
2014-03-09 00:01:49 +00:00
tx : b . tx ,
root : b . root ,
stack : make ( [ ] elemRef , 0 ) ,
2014-01-26 22:29:06 +00:00
}
}
2014-02-21 16:20:45 +00:00
2014-02-23 06:08:30 +00:00
// 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.
2014-03-09 03:25:37 +00:00
c . node ( b . tx ) . put ( key , key , value , 0 )
2014-02-23 06:08:30 +00:00
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.
2014-03-09 03:25:37 +00:00
c . node ( b . tx ) . del ( key )
2014-02-23 06:08:30 +00:00
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.
2014-03-15 15:14:20 +00:00
// If the provided function returns an error then the iteration is stopped and
// the error is returned to the caller.
2014-02-23 06:08:30 +00:00
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
}
2014-02-21 16:20:45 +00:00
// Stat returns stats on a bucket.
func ( b * Bucket ) Stat ( ) * BucketStat {
s := & BucketStat { }
2014-03-09 00:01:49 +00:00
b . tx . forEachPage ( b . root , 0 , func ( p * page , depth int ) {
2014-02-21 16:20:45 +00:00
if ( p . flags & leafPageFlag ) != 0 {
s . LeafPageCount ++
s . KeyCount += int ( p . count )
} else if ( p . flags & branchPageFlag ) != 0 {
s . BranchPageCount ++
}
s . OverflowPageCount += int ( p . overflow )
if depth + 1 > s . MaxDepth {
s . MaxDepth = ( depth + 1 )
}
} )
return s
}
// BucketStat represents stats on a bucket such as branch pages and leaf pages.
type BucketStat struct {
BranchPageCount int
LeafPageCount int
OverflowPageCount int
KeyCount int
MaxDepth int
}
2014-03-13 21:08:59 +00:00
type bucketsByName [ ] * Bucket
func ( s bucketsByName ) Len ( ) int { return len ( s ) }
func ( s bucketsByName ) Swap ( i , j int ) { s [ i ] , s [ j ] = s [ j ] , s [ i ] }
func ( s bucketsByName ) Less ( i , j int ) bool { return s [ i ] . name < s [ j ] . name }