func (cmd *BenchCommand) runReadsSequential(db *bolt.DB, options *BenchOptions, results *BenchResults) error { return db.View(func(tx *bolt.Tx) error { t := time.Now() for { var count int c := tx.Bucket(benchBucketName).Cursor() for k, v := c.First(); k != nil; k, v = c.Next() { if v == nil { return errors.New("invalid value") } count++ } if options.WriteMode == "seq" && count != options.Iterations { return fmt.Errorf("read seq: iter mismatch: expected %d, got %d", options.Iterations, count) } results.ReadOps += count // Make sure we do this for at least a second. if time.Since(t) >= time.Second { break } } return nil }) }
func (cmd *BenchCommand) runReadsSequentialNested(db *bolt.DB, options *BenchOptions, results *BenchResults) error { return db.View(func(tx *bolt.Tx) error { t := time.Now() for { var count int var top = tx.Bucket(benchBucketName) if err := top.ForEach(func(name, _ []byte) error { c := top.Bucket(name).Cursor() for k, v := c.First(); k != nil; k, v = c.Next() { if v == nil { return ErrInvalidValue } count++ } return nil }); err != nil { return err } if options.WriteMode == "seq-nest" && count != options.Iterations { return fmt.Errorf("read seq-nest: iter mismatch: expected %d, got %d", options.Iterations, count) } results.ReadOps += count // Make sure we do this for at least a second. if time.Since(t) >= time.Second { break } } return nil }) }
func (cmd *BenchCommand) runWritesWithSource(db *bolt.DB, options *BenchOptions, results *BenchResults, keySource func() uint32) error { results.WriteOps = options.Iterations for i := 0; i < options.Iterations; i += options.BatchSize { if err := db.Update(func(tx *bolt.Tx) error { b, _ := tx.CreateBucketIfNotExists(benchBucketName) b.FillPercent = options.FillPercent for j := 0; j < options.BatchSize; j++ { key := make([]byte, options.KeySize) value := make([]byte, options.ValueSize) // Write key as uint32. binary.BigEndian.PutUint32(key, keySource()) // Insert key/value. if err := b.Put(key, value); err != nil { return err } } return nil }); err != nil { return err } } return nil }
func benchWriteNestedWithSource(db *bolt.DB, options *BenchOptions, results *BenchResults, keySource func() uint32) error { results.WriteOps = options.Iterations for i := 0; i < options.Iterations; i += options.BatchSize { err := db.Update(func(tx *bolt.Tx) error { top, _ := tx.CreateBucketIfNotExists(benchBucketName) top.FillPercent = options.FillPercent var name = make([]byte, options.KeySize) binary.BigEndian.PutUint32(name, keySource()) b, _ := top.CreateBucketIfNotExists(name) b.FillPercent = options.FillPercent for j := 0; j < options.BatchSize; j++ { var key = make([]byte, options.KeySize) var value = make([]byte, options.ValueSize) binary.BigEndian.PutUint32(key, keySource()) if err := b.Put(key, value); err != nil { return err } } return nil }) if err != nil { return err } } return nil }
// Ensure a closed database returns an error while running a transaction block func TestDB_Update_Closed(t *testing.T) { var db bolt.DB err := db.Update(func(tx *bolt.Tx) error { tx.CreateBucket([]byte("widgets")) return nil }) equals(t, err, bolt.ErrDatabaseNotOpen) }
func (cmd *BenchCommand) runWritesNestedWithSource(db *bolt.DB, options *BenchOptions, results *BenchResults, keySource func() uint32) error { results.WriteOps = options.Iterations for i := 0; i < options.Iterations; i += options.BatchSize { if err := db.Update(func(tx *bolt.Tx) error { top, err := tx.CreateBucketIfNotExists(benchBucketName) if err != nil { return err } top.FillPercent = options.FillPercent // Create bucket key. name := make([]byte, options.KeySize) binary.BigEndian.PutUint32(name, keySource()) // Create bucket. b, err := top.CreateBucketIfNotExists(name) if err != nil { return err } b.FillPercent = options.FillPercent for j := 0; j < options.BatchSize; j++ { var key = make([]byte, options.KeySize) var value = make([]byte, options.ValueSize) // Generate key as uint32. binary.BigEndian.PutUint32(key, keySource()) // Insert value into subbucket. if err := b.Put(key, value); err != nil { return err } } return nil }); err != nil { return err } } return nil }
// Continuously prints stats on the database at given intervals. func printStats(db *bolt.DB, interval time.Duration) { var prevStats = db.Stats() var encoder = json.NewEncoder(os.Stdout) for { // Wait for the stats interval. time.Sleep(interval) // Retrieve new stats and find difference from previous iteration. var stats = db.Stats() var diff = stats.Sub(&prevStats) // Print as JSON to STDOUT. if err := encoder.Encode(diff); err != nil { fatal(err) } // Save stats for next iteration. prevStats = stats } }
// Ensure that opening a transaction while the DB is closed returns an error. func TestDB_BeginRW_Closed(t *testing.T) { var db bolt.DB tx, err := db.Begin(true) equals(t, err, bolt.ErrDatabaseNotOpen) assert(t, tx == nil, "") }
// Ensure that a database cannot open a transaction when it's not open. func TestDB_Begin_DatabaseNotOpen(t *testing.T) { var db bolt.DB tx, err := db.Begin(false) assert(t, tx == nil, "") equals(t, err, bolt.ErrDatabaseNotOpen) }