/* * Copyright (c) 2014 Conformal Systems LLC * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ package walletdb_test import ( "bytes" "fmt" "os" "path/filepath" "github.com/conformal/btcwallet/walletdb" _ "github.com/conformal/btcwallet/walletdb/bdb" ) // This example demonstrates creating a new database. func ExampleCreate() { // This example assumes the bdb (bolt db) driver is imported. // // import ( // "github.com/conformal/btcwallet/walletdb" // _ "github.com/conformal/btcwallet/walletdb/bdb" // ) // Create a database and schedule it to be closed and removed on exit. // Typically you wouldn't want to remove the database right away like // this, but it's done here in the example to ensure the example cleans // up after itself. dbPath := filepath.Join(os.TempDir(), "examplecreate.db") db, err := walletdb.Create("bdb", dbPath) if err != nil { fmt.Println(err) return } defer os.Remove(dbPath) defer db.Close() // Output: } // exampleNum is used as a counter in the exampleLoadDB function to provided // a unique database name for each example. var exampleNum = 0 // exampleLoadDB is used in the examples to elide the setup code. func exampleLoadDB() (walletdb.DB, func(), error) { dbName := fmt.Sprintf("exampleload%d.db", exampleNum) dbPath := filepath.Join(os.TempDir(), dbName) db, err := walletdb.Create("bdb", dbPath) if err != nil { return nil, nil, err } teardownFunc := func() { db.Close() os.Remove(dbPath) } exampleNum++ return db, teardownFunc, err } // This example demonstrates creating a new namespace. func ExampleDB_namespace() { // Load a database for the purposes of this example and schedule it to // be closed and removed on exit. See the Create example for more // details on what this step is doing. db, teardownFunc, err := exampleLoadDB() if err != nil { fmt.Println(err) return } defer teardownFunc() // Get or create a namespace in the database as needed. This namespace // is what is typically passed to specific sub-packages so they have // their own area to work in without worrying about conflicting keys. namespaceKey := []byte("walletsubpackage") namespace, err := db.Namespace(namespaceKey) if err != nil { fmt.Println(err) return } // Prevent unused error. Ordinarily the namespace would be used at this // point to start a managed or manual transaction. _ = namespace // Output: } // This example demonstrates creating a new database, getting a namespace from // it, and using a managed read-write transaction against the namespace to store // and retrieve data. func Example_basicUsage() { // This example assumes the bdb (bolt db) driver is imported. // // import ( // "github.com/conformal/btcwallet/walletdb" // _ "github.com/conformal/btcwallet/walletdb/bdb" // ) // Create a database and schedule it to be closed and removed on exit. // Typically you wouldn't want to remove the database right away like // this, but it's done here in the example to ensure the example cleans // up after itself. dbPath := filepath.Join(os.TempDir(), "exampleusage.db") db, err := walletdb.Create("bdb", dbPath) if err != nil { fmt.Println(err) return } defer os.Remove(dbPath) defer db.Close() // Get or create a namespace in the database as needed. This namespace // is what is typically passed to specific sub-packages so they have // their own area to work in without worrying about conflicting keys. namespaceKey := []byte("walletsubpackage") namespace, err := db.Namespace(namespaceKey) if err != nil { fmt.Println(err) return } // Use the Update function of the namespace to perform a managed // read-write transaction. The transaction will automatically be rolled // back if the supplied inner function returns a non-nil error. err = namespace.Update(func(tx walletdb.Tx) error { // All data is stored against the root bucket of the namespace, // or nested buckets of the root bucket. It's not really // necessary to store it in a separate variable like this, but // it has been done here for the purposes of the example to // illustrate. rootBucket := tx.RootBucket() // Store a key/value pair directly in the root bucket. key := []byte("mykey") value := []byte("myvalue") if err := rootBucket.Put(key, value); err != nil { return err } // Read the key back and ensure it matches. if !bytes.Equal(rootBucket.Get(key), value) { return fmt.Errorf("unexpected value for key '%s'", key) } // Create a new nested bucket under the root bucket. nestedBucketKey := []byte("mybucket") nestedBucket, err := rootBucket.CreateBucket(nestedBucketKey) if err != nil { return err } // The key from above that was set in the root bucket does not // exist in this new nested bucket. if nestedBucket.Get(key) != nil { return fmt.Errorf("key '%s' is not expected nil", key) } return nil }) if err != nil { fmt.Println(err) return } // Output: }