func ExampleTx_CopyFile() { // Open the database. db, _ := bolt.Open(tempfile(), 0666, nil) defer os.Remove(db.Path()) defer db.Close() // Create a bucket and a key. db.Update(func(tx *bolt.Tx) error { tx.CreateBucket([]byte("widgets")) tx.Bucket([]byte("widgets")).Put([]byte("foo"), []byte("bar")) return nil }) // Copy the database to another file. toFile := tempfile() db.View(func(tx *bolt.Tx) error { return tx.CopyFile(toFile, 0666) }) defer os.Remove(toFile) // Open the cloned database. db2, _ := bolt.Open(toFile, 0666, nil) defer db2.Close() // Ensure that the key exists in the copy. db2.View(func(tx *bolt.Tx) error { value := tx.Bucket([]byte("widgets")).Get([]byte("foo")) fmt.Printf("The value for 'foo' in the clone is: %s\n", value) return nil }) // Output: // The value for 'foo' in the clone is: bar }
// Ensure that a re-opened database is consistent. func TestOpen_Check(t *testing.T) { path := tempfile() defer os.Remove(path) db, err := bolt.Open(path, 0666, nil) ok(t, err) ok(t, db.View(func(tx *bolt.Tx) error { return <-tx.Check() })) db.Close() db, err = bolt.Open(path, 0666, nil) ok(t, err) ok(t, db.View(func(tx *bolt.Tx) error { return <-tx.Check() })) db.Close() }
// Ensure that a database that is too small returns an error. func TestDB_Open_FileTooSmall(t *testing.T) { path := tempfile() defer os.Remove(path) db, err := bolt.Open(path, 0666, nil) ok(t, err) db.Close() // corrupt the database ok(t, os.Truncate(path, int64(os.Getpagesize()))) db, err = bolt.Open(path, 0666, nil) equals(t, errors.New("file size too small"), err) }
// Keys retrieves a list of keys for a given bucket. func Keys(path, name string) { if _, err := os.Stat(path); os.IsNotExist(err) { fatal(err) return } db, err := bolt.Open(path, 0600, nil) if err != nil { fatal(err) return } defer db.Close() err = db.View(func(tx *bolt.Tx) error { // Find bucket. b := tx.Bucket([]byte(name)) if b == nil { fatalf("bucket not found: %s", name) return nil } // Iterate over each key. return b.ForEach(func(key, _ []byte) error { println(string(key)) return nil }) }) if err != nil { fatal(err) return } }
// Ensure that a database can be imported. func TestImport(t *testing.T) { SetTestMode(true) // Write input file. input := tempfile() ok(t, ioutil.WriteFile(input, []byte(`[{"type":"bucket","key":"ZW1wdHk=","value":[]},{"type":"bucket","key":"d2lkZ2V0cw==","value":[{"key":"YmFy","value":""},{"key":"Zm9v","value":"MDAwMA=="}]},{"type":"bucket","key":"d29vaml0cw==","value":[{"key":"YmF6","value":"WFhYWA=="},{"type":"bucket","key":"d29vaml0cy9zdWJidWNrZXQ=","value":[{"key":"YmF0","value":"QQ=="}]}]}]`), 0600)) // Import database. path := tempfile() output := run("import", path, "--input", input) equals(t, ``, output) // Open database and verify contents. db, err := bolt.Open(path, 0600, nil) ok(t, err) db.View(func(tx *bolt.Tx) error { assert(t, tx.Bucket([]byte("empty")) != nil, "") b := tx.Bucket([]byte("widgets")) assert(t, b != nil, "") equals(t, []byte("0000"), b.Get([]byte("foo"))) equals(t, []byte(""), b.Get([]byte("bar"))) b = tx.Bucket([]byte("woojits")) assert(t, b != nil, "") equals(t, []byte("XXXX"), b.Get([]byte("baz"))) b = b.Bucket([]byte("woojits/subbucket")) equals(t, []byte("A"), b.Get([]byte("bat"))) return nil }) db.Close() }
// Run executes the command. func (cmd *InfoCommand) Run(args ...string) error { // Parse flags. fs := flag.NewFlagSet("", flag.ContinueOnError) help := fs.Bool("h", false, "") if err := fs.Parse(args); err != nil { return err } else if *help { fmt.Fprintln(cmd.Stderr, cmd.Usage()) return ErrUsage } // Require database path. path := fs.Arg(0) if path == "" { return ErrPathRequired } else if _, err := os.Stat(path); os.IsNotExist(err) { return ErrFileNotFound } // Open the database. db, err := bolt.Open(path, 0666, nil) if err != nil { return err } defer db.Close() // Print basic database info. info := db.Info() fmt.Fprintf(cmd.Stdout, "Page Size: %d\n", info.PageSize) return nil }
// OpenDB opens and initialises the persistence DB, if not already open. func (m *Manager) OpenDB() error { if m.dbPath == "" { return nil } m.dbMtx.Lock() defer m.dbMtx.Unlock() // open/initialize db if err := os.MkdirAll(filepath.Dir(m.dbPath), 0755); err != nil { return fmt.Errorf("could not mkdir for volume persistence db: %s", err) } db, err := bolt.Open(m.dbPath, 0600, &bolt.Options{Timeout: 5 * time.Second}) if err != nil { return fmt.Errorf("could not open volume persistence db: %s", err) } if err := db.Update(func(tx *bolt.Tx) error { // idempotently create buckets. (errors ignored because they're all compile-time impossible args checks.) tx.CreateBucketIfNotExists([]byte("volumes")) tx.CreateBucketIfNotExists([]byte("providers")) return nil }); err != nil { return fmt.Errorf("could not initialize volume persistence db: %s", err) } m.db = db if err := m.restore(); err != nil { return err } return m.maybeInitDefaultProvider() }
func ExampleBucket_ForEach() { // Open the database. db, _ := bolt.Open(tempfile(), 0666, nil) defer os.Remove(db.Path()) defer db.Close() // Insert data into a bucket. db.Update(func(tx *bolt.Tx) error { tx.CreateBucket([]byte("animals")) b := tx.Bucket([]byte("animals")) b.Put([]byte("dog"), []byte("fun")) b.Put([]byte("cat"), []byte("lame")) b.Put([]byte("liger"), []byte("awesome")) // Iterate over items in sorted key order. b.ForEach(func(k, v []byte) error { fmt.Printf("A %s is %s.\n", k, v) return nil }) return nil }) // Output: // A cat is lame. // A dog is fun. // A liger is awesome. }
func ExampleBucket_Put() { // Open the database. db, _ := bolt.Open(tempfile(), 0666, nil) defer os.Remove(db.Path()) defer db.Close() // Start a write transaction. db.Update(func(tx *bolt.Tx) error { // Create a bucket. tx.CreateBucket([]byte("widgets")) // Set the value "bar" for the key "foo". tx.Bucket([]byte("widgets")).Put([]byte("foo"), []byte("bar")) return nil }) // Read value back in a different read-only transaction. db.View(func(tx *bolt.Tx) error { value := tx.Bucket([]byte("widgets")).Get([]byte("foo")) fmt.Printf("The value of 'foo' is: %s\n", value) return nil }) // Output: // The value of 'foo' is: bar }
func ExampleDB_Begin_ReadOnly() { // Open the database. db, _ := bolt.Open(tempfile(), 0666, nil) defer os.Remove(db.Path()) defer db.Close() // Create a bucket. db.Update(func(tx *bolt.Tx) error { _, err := tx.CreateBucket([]byte("widgets")) return err }) // Create several keys in a transaction. tx, _ := db.Begin(true) b := tx.Bucket([]byte("widgets")) b.Put([]byte("john"), []byte("blue")) b.Put([]byte("abby"), []byte("red")) b.Put([]byte("zephyr"), []byte("purple")) tx.Commit() // Iterate over the values in sorted key order. tx, _ = db.Begin(false) c := tx.Bucket([]byte("widgets")).Cursor() for k, v := c.First(); k != nil; k, v = c.Next() { fmt.Printf("%s likes %s\n", k, v) } tx.Rollback() // Output: // abby likes red // john likes blue // zephyr likes purple }
// NewTestDB returns a new instance of TestDB. func NewTestDB() *TestDB { db, err := bolt.Open(tempfile(), 0666, nil) if err != nil { panic("cannot open db: " + err.Error()) } return &TestDB{db} }
func ExampleDB_View() { // Open the database. db, _ := bolt.Open(tempfile(), 0666, nil) defer os.Remove(db.Path()) defer db.Close() // Insert data into a bucket. db.Update(func(tx *bolt.Tx) error { tx.CreateBucket([]byte("people")) b := tx.Bucket([]byte("people")) b.Put([]byte("john"), []byte("doe")) b.Put([]byte("susy"), []byte("que")) return nil }) // Access data from within a read-only transactional block. db.View(func(tx *bolt.Tx) error { v := tx.Bucket([]byte("people")).Get([]byte("john")) fmt.Printf("John's last name is %s.\n", v) return nil }) // Output: // John's last name is doe. }
func ExampleDB_Update() { // Open the database. db, _ := bolt.Open(tempfile(), 0666, nil) defer os.Remove(db.Path()) defer db.Close() // Execute several commands within a write transaction. err := db.Update(func(tx *bolt.Tx) error { b, err := tx.CreateBucket([]byte("widgets")) if err != nil { return err } if err := b.Put([]byte("foo"), []byte("bar")); err != nil { return err } return nil }) // If our transactional block didn't return an error then our data is saved. if err == nil { db.View(func(tx *bolt.Tx) error { value := tx.Bucket([]byte("widgets")).Get([]byte("foo")) fmt.Printf("The value of 'foo' is: %s\n", value) return nil }) } // Output: // The value of 'foo' is: bar }
// OpenDB opens and initialises the persistence DB, if not already open. func (s *State) OpenDB() error { s.dbCond.L.Lock() defer s.dbCond.L.Unlock() if s.stateDB != nil { return nil } // open/initialize db if err := os.MkdirAll(filepath.Dir(s.stateFilePath), 0755); err != nil { return fmt.Errorf("could not not mkdir for db: %s", err) } stateDB, err := bolt.Open(s.stateFilePath, 0600, &bolt.Options{Timeout: 5 * time.Second}) if err != nil { return fmt.Errorf("could not open db: %s", err) } s.stateDB = stateDB if err := s.stateDB.Update(func(tx *bolt.Tx) error { // idempotently create buckets. (errors ignored because they're all compile-time impossible args checks.) tx.CreateBucketIfNotExists([]byte("jobs")) tx.CreateBucketIfNotExists([]byte("backend-jobs")) tx.CreateBucketIfNotExists([]byte("backend-global")) tx.CreateBucketIfNotExists([]byte("persistent-jobs")) return nil }); err != nil { return fmt.Errorf("could not initialize host persistence db: %s", err) } return nil }
func ExampleTx_Rollback() { // Open the database. db, _ := bolt.Open(tempfile(), 0666, nil) defer os.Remove(db.Path()) defer db.Close() // Create a bucket. db.Update(func(tx *bolt.Tx) error { _, err := tx.CreateBucket([]byte("widgets")) return err }) // Set a value for a key. db.Update(func(tx *bolt.Tx) error { return tx.Bucket([]byte("widgets")).Put([]byte("foo"), []byte("bar")) }) // Update the key but rollback the transaction so it never saves. tx, _ := db.Begin(true) b := tx.Bucket([]byte("widgets")) b.Put([]byte("foo"), []byte("baz")) tx.Rollback() // Ensure that our original value is still set. db.View(func(tx *bolt.Tx) error { value := tx.Bucket([]byte("widgets")).Get([]byte("foo")) fmt.Printf("The value for 'foo' is still: %s\n", value) return nil }) // Output: // The value for 'foo' is still: bar }
// Ensure that a database can be opened without error. func TestOpen(t *testing.T) { path := tempfile() defer os.Remove(path) db, err := bolt.Open(path, 0666, nil) assert(t, db != nil, "") ok(t, err) equals(t, db.Path(), path) ok(t, db.Close()) }
func (r *Runner) start() error { r.githubToken = os.Getenv("GITHUB_TOKEN") if r.githubToken == "" { return errors.New("GITHUB_TOKEN not set") } awsAuth, err := aws.EnvAuth() if err != nil { return err } r.s3Bucket = s3.New(awsAuth, aws.USEast).Bucket(logBucket) bc := r.bc bc.Network, err = r.allocateNet() if err != nil { return err } if r.rootFS, err = cluster.BuildFlynn(bc, args.RootFS, "origin/master", false, os.Stdout); err != nil { return fmt.Errorf("could not build flynn: %s", err) } r.releaseNet(bc.Network) defer os.RemoveAll(r.rootFS) db, err := bolt.Open(args.DBPath, 0600, &bolt.Options{Timeout: 5 * time.Second}) if err != nil { return fmt.Errorf("could not open db: %s", err) } r.db = db defer r.db.Close() if err := r.db.Update(func(tx *bolt.Tx) error { _, err := tx.CreateBucketIfNotExists(dbBucket) return err }); err != nil { return fmt.Errorf("could not create builds bucket: %s", err) } for i := 0; i < maxBuilds; i++ { r.buildCh <- struct{}{} } if err := r.buildPending(); err != nil { log.Printf("could not build pending builds: %s", err) } go r.watchEvents() http.HandleFunc("/", r.httpEventHandler) http.HandleFunc("/builds", r.httpBuildHandler) http.Handle("/assets/", http.StripPrefix("/assets/", http.FileServer(http.Dir(args.AssetsDir)))) handler := handlers.CombinedLoggingHandler(os.Stdout, http.DefaultServeMux) log.Println("Listening on", args.ListenAddr, "...") if err := http.ListenAndServeTLS(args.ListenAddr, args.TLSCert, args.TLSKey, handler); err != nil { return fmt.Errorf("ListenAndServeTLS: %s", err) } return nil }
// Ensure that the database returns an error if the file handle cannot be open. func TestDB_Open_FileError(t *testing.T) { path := tempfile() defer os.Remove(path) _, err := bolt.Open(path+"/youre-not-my-real-parent", 0666, nil) assert(t, err.(*os.PathError) != nil, "") equals(t, path+"/youre-not-my-real-parent", err.(*os.PathError).Path) equals(t, "open", err.(*os.PathError).Op) }
func (r *Runner) start() error { r.githubToken = os.Getenv("GITHUB_TOKEN") if r.githubToken == "" { return errors.New("GITHUB_TOKEN not set") } awsAuth, err := aws.EnvAuth() if err != nil { return err } r.s3Bucket = s3.New(awsAuth, aws.USEast).Bucket(logBucket) if r.dockerFS == "" { var err error bc := r.bc bc.Network, err = r.allocateNet() if err != nil { return err } if r.dockerFS, err = cluster.BuildFlynn(bc, "", "master", os.Stdout); err != nil { return fmt.Errorf("could not build flynn: %s", err) } r.releaseNet(bc.Network) defer os.RemoveAll(r.dockerFS) } db, err := bolt.Open(args.DBPath, 0600, &bolt.Options{Timeout: 5 * time.Second}) if err != nil { return fmt.Errorf("could not open db: %s", err) } r.db = db defer r.db.Close() if err := r.db.Update(func(tx *bolt.Tx) error { _, err := tx.CreateBucketIfNotExists([]byte("pending-builds")) return err }); err != nil { return fmt.Errorf("could not create pending-builds bucket: %s", err) } for i := 0; i < maxBuilds; i++ { r.buildCh <- struct{}{} } if err := r.buildPending(); err != nil { log.Printf("could not build pending builds: %s", err) } go r.watchEvents() http.Handle("/", handlers.CombinedLoggingHandler(os.Stdout, http.HandlerFunc(r.httpEventHandler))) log.Println("Listening on :80...") if err := http.ListenAndServe(":80", nil); err != nil { return fmt.Errorf("ListenAndServer: %s", err) } return nil }
func ExampleDB_Batch() { // Open the database. db, _ := bolt.Open(tempfile(), 0666, nil) defer os.Remove(db.Path()) defer db.Close() // Start our web server count := counter{db} srv := httptest.NewServer(count) defer srv.Close() // Decrease the batch size to make things more interesting. db.MaxBatchSize = 3 // Get every path multiple times concurrently. const clients = 10 paths := []string{ "/foo", "/bar", "/baz", "/quux", "/thud", "/xyzzy", } errors := make(chan error, clients) for i := 0; i < clients; i++ { go func(id int) { errors <- client(id, srv.URL, paths) }(i) } // Check all responses to make sure there's no error. for i := 0; i < clients; i++ { if err := <-errors; err != nil { fmt.Printf("client error: %v", err) return } } // Check the final result db.View(func(tx *bolt.Tx) error { b := tx.Bucket([]byte("hits")) c := b.Cursor() for k, v := c.First(); k != nil; k, v = c.Next() { fmt.Printf("hits to %s: %d\n", k, decode(v)) } return nil }) // Output: // hits to /bar: 10 // hits to /baz: 10 // hits to /foo: 10 // hits to /quux: 10 // hits to /thud: 10 // hits to /xyzzy: 10 }
// open creates and opens a Bolt database in the temp directory. func open(fn func(*bolt.DB, string)) { path := tempfile() defer os.RemoveAll(path) db, err := bolt.Open(path, 0600, nil) if err != nil { panic("db open error: " + err.Error()) } fn(db, path) }
// Run executes the command. func (cmd *CheckCommand) Run(args ...string) error { // Parse flags. fs := flag.NewFlagSet("", flag.ContinueOnError) help := fs.Bool("h", false, "") if err := fs.Parse(args); err != nil { return err } else if *help { fmt.Fprintln(cmd.Stderr, cmd.Usage()) return ErrUsage } // Require database path. path := fs.Arg(0) if path == "" { return ErrPathRequired } else if _, err := os.Stat(path); os.IsNotExist(err) { return ErrFileNotFound } // Open database. db, err := bolt.Open(path, 0666, nil) if err != nil { return err } defer db.Close() // Perform consistency check. return db.View(func(tx *bolt.Tx) error { var count int ch := tx.Check() loop: for { select { case err, ok := <-ch: if !ok { break loop } fmt.Fprintln(cmd.Stdout, err) count++ } } // Print summary of errors. if count > 0 { fmt.Fprintf(cmd.Stdout, "%d errors found\n", count) return ErrCorrupt } // Notify user that database is valid. fmt.Fprintln(cmd.Stdout, "OK") return nil }) }
// MustOpen creates a Bolt database in a temporary location. func MustOpen(mode os.FileMode, options *bolt.Options) *DB { // Create temporary path. f, _ := ioutil.TempFile("", "bolt-") f.Close() os.Remove(f.Name()) db, err := bolt.Open(f.Name(), mode, options) if err != nil { panic(err.Error()) } return &DB{DB: db, Path: f.Name()} }
// Ensure that opening an already open database file will timeout. func TestOpen_Timeout(t *testing.T) { if runtime.GOOS == "windows" { t.Skip("timeout not supported on windows") } path := tempfile() defer os.Remove(path) // Open a data file. db0, err := bolt.Open(path, 0666, nil) assert(t, db0 != nil, "") ok(t, err) // Attempt to open the database again. start := time.Now() db1, err := bolt.Open(path, 0666, &bolt.Options{Timeout: 100 * time.Millisecond}) assert(t, db1 == nil, "") equals(t, bolt.ErrTimeout, err) assert(t, time.Since(start) > 100*time.Millisecond, "") db0.Close() }
func FileLocalStore(path string) (LocalStore, error) { db, err := bolt.Open(path, 0600, &bolt.Options{Timeout: time.Second}) if err != nil { return nil, err } if err := db.Update(func(tx *bolt.Tx) error { _, err := tx.CreateBucketIfNotExists([]byte(dbBucket)) return err }); err != nil { return nil, err } return &fileLocalStore{db: db}, nil }
// Ensure that opening an already open database file will wait until its closed. func TestOpen_Wait(t *testing.T) { if runtime.GOOS == "solaris" { t.Skip("solaris fcntl locks don't support intra-process locking") } path := tempfile() defer os.Remove(path) // Open a data file. db0, err := bolt.Open(path, 0666, nil) assert(t, db0 != nil, "") ok(t, err) // Close it in just a bit. time.AfterFunc(100*time.Millisecond, func() { db0.Close() }) // Attempt to open the database again. start := time.Now() db1, err := bolt.Open(path, 0666, &bolt.Options{Timeout: 200 * time.Millisecond}) assert(t, db1 != nil, "") ok(t, err) assert(t, time.Since(start) > 100*time.Millisecond, "") }
// Ensure that opening a database beyond the max step size does not increase its size. // https://github.com/boltdb/bolt/issues/303 func TestOpen_Size_Large(t *testing.T) { if testing.Short() { t.Skip("short mode") } // Open a data file. db := NewTestDB() path := db.Path() defer db.Close() // Insert until we get above the minimum 4MB size. var index uint64 for i := 0; i < 10000; i++ { ok(t, db.Update(func(tx *bolt.Tx) error { b, _ := tx.CreateBucketIfNotExists([]byte("data")) for j := 0; j < 1000; j++ { ok(t, b.Put(u64tob(index), make([]byte, 50))) index++ } return nil })) } // Close database and grab the size. db.DB.Close() sz := fileSize(path) if sz == 0 { t.Fatalf("unexpected new file size: %d", sz) } else if sz < (1 << 30) { t.Fatalf("expected larger initial size: %d", sz) } // Reopen database, update, and check size again. db0, err := bolt.Open(path, 0666, nil) ok(t, err) ok(t, db0.Update(func(tx *bolt.Tx) error { return tx.Bucket([]byte("data")).Put([]byte{0}, []byte{0}) })) ok(t, db0.Close()) newSz := fileSize(path) if newSz == 0 { t.Fatalf("unexpected new file size: %d", newSz) } // Compare the original size with the new size. if sz != newSz { t.Fatalf("unexpected file growth: %d => %d", sz, newSz) } }
// Pages prints a list of all pages in a database. func Pages(path string) { if _, err := os.Stat(path); os.IsNotExist(err) { fatal(err) return } db, err := bolt.Open(path, 0600, nil) if err != nil { fatal(err) return } defer db.Close() println("ID TYPE ITEMS OVRFLW") println("======== ========== ====== ======") db.Update(func(tx *bolt.Tx) error { var id int for { p, err := tx.Page(id) if err != nil { fatalf("page error: %d: %s", id, err) } else if p == nil { break } // Only display count and overflow if this is a non-free page. var count, overflow string if p.Type != "free" { count = strconv.Itoa(p.Count) if p.OverflowCount > 0 { overflow = strconv.Itoa(p.OverflowCount) } } // Print table row. printf("%-8d %-10s %-6s %-6s\n", p.ID, p.Type, count, overflow) // Move to the next non-overflow page. id += 1 if p.Type != "free" { id += p.OverflowCount } } return nil }) }
// Info prints basic information about a database. func Info(path string) { if _, err := os.Stat(path); os.IsNotExist(err) { fatal(err) return } db, err := bolt.Open(path, 0600, nil) if err != nil { fatal(err) return } defer db.Close() // Print basic database info. var info = db.Info() printf("Page Size: %d", info.PageSize) }
func TestNewBoltStore(t *testing.T) { fh, err := ioutil.TempFile("", "bolt") if err != nil { t.Fatalf("err: %s", err) } os.Remove(fh.Name()) defer os.Remove(fh.Name()) // Successfully creates and returns a store store, err := NewBoltStore(fh.Name()) if err != nil { t.Fatalf("err: %s", err) } // Ensure the file was created if store.path != fh.Name() { t.Fatalf("unexpected file path %q", store.path) } if _, err := os.Stat(fh.Name()); err != nil { t.Fatalf("err: %s", err) } // Close the store so we can open again if err := store.Close(); err != nil { t.Fatalf("err: %s", err) } // Ensure our tables were created db, err := bolt.Open(fh.Name(), dbFileMode, nil) if err != nil { t.Fatalf("err: %s", err) } tx, err := db.Begin(true) if err != nil { t.Fatalf("err: %s", err) } if _, err := tx.CreateBucket([]byte(dbLogs)); err != bolt.ErrBucketExists { t.Fatalf("bad: %v", err) } if _, err := tx.CreateBucket([]byte(dbConf)); err != bolt.ErrBucketExists { t.Fatalf("bad: %v", err) } }