github.com/btcsuite/btcwallet/walletdb@v1.4.2/example_test.go (about) 1 // Copyright (c) 2014 The btcsuite developers 2 // Use of this source code is governed by an ISC 3 // license that can be found in the LICENSE file. 4 5 package walletdb_test 6 7 import ( 8 "bytes" 9 "fmt" 10 "os" 11 "path/filepath" 12 13 "github.com/btcsuite/btcwallet/walletdb" 14 _ "github.com/btcsuite/btcwallet/walletdb/bdb" 15 ) 16 17 // This example demonstrates creating a new database. 18 func ExampleCreate() { 19 // This example assumes the bdb (bolt db) driver is imported. 20 // 21 // import ( 22 // "github.com/btcsuite/btcwallet/walletdb" 23 // _ "github.com/btcsuite/btcwallet/walletdb/bdb" 24 // ) 25 26 // Create a database and schedule it to be closed and removed on exit. 27 // Typically you wouldn't want to remove the database right away like 28 // this, but it's done here in the example to ensure the example cleans 29 // up after itself. 30 dbPath := filepath.Join(os.TempDir(), "examplecreate.db") 31 db, err := walletdb.Create("bdb", dbPath, true, defaultDBTimeout) 32 if err != nil { 33 fmt.Println(err) 34 return 35 } 36 defer os.Remove(dbPath) 37 defer db.Close() 38 39 // Output: 40 } 41 42 // exampleNum is used as a counter in the exampleLoadDB function to provided 43 // a unique database name for each example. 44 var exampleNum = 0 45 46 // exampleLoadDB is used in the examples to elide the setup code. 47 func exampleLoadDB() (walletdb.DB, func(), error) { 48 dbName := fmt.Sprintf("exampleload%d.db", exampleNum) 49 dbPath := filepath.Join(os.TempDir(), dbName) 50 db, err := walletdb.Create("bdb", dbPath, true, defaultDBTimeout) 51 if err != nil { 52 return nil, nil, err 53 } 54 teardownFunc := func() { 55 db.Close() 56 os.Remove(dbPath) 57 } 58 exampleNum++ 59 60 return db, teardownFunc, err 61 } 62 63 // This example demonstrates creating a new top level bucket. 64 func ExampleDB_createTopLevelBucket() { 65 // Load a database for the purposes of this example and schedule it to 66 // be closed and removed on exit. See the Create example for more 67 // details on what this step is doing. 68 db, teardownFunc, err := exampleLoadDB() 69 if err != nil { 70 fmt.Println(err) 71 return 72 } 73 defer teardownFunc() 74 75 dbtx, err := db.BeginReadWriteTx() 76 if err != nil { 77 fmt.Println(err) 78 return 79 } 80 defer dbtx.Commit() 81 82 // Get or create a bucket in the database as needed. This bucket 83 // is what is typically passed to specific sub-packages so they have 84 // their own area to work in without worrying about conflicting keys. 85 bucketKey := []byte("walletsubpackage") 86 bucket, err := dbtx.CreateTopLevelBucket(bucketKey) 87 if err != nil { 88 fmt.Println(err) 89 return 90 } 91 92 // Prevent unused error. 93 _ = bucket 94 95 // Output: 96 } 97 98 // This example demonstrates creating a new database, getting a namespace from 99 // it, and using a managed read-write transaction against the namespace to store 100 // and retrieve data. 101 func Example_basicUsage() { 102 // This example assumes the bdb (bolt db) driver is imported. 103 // 104 // import ( 105 // "github.com/btcsuite/btcwallet/walletdb" 106 // _ "github.com/btcsuite/btcwallet/walletdb/bdb" 107 // ) 108 109 // Create a database and schedule it to be closed and removed on exit. 110 // Typically you wouldn't want to remove the database right away like 111 // this, but it's done here in the example to ensure the example cleans 112 // up after itself. 113 dbPath := filepath.Join(os.TempDir(), "exampleusage.db") 114 db, err := walletdb.Create("bdb", dbPath, true, defaultDBTimeout) 115 if err != nil { 116 fmt.Println(err) 117 return 118 } 119 defer os.Remove(dbPath) 120 defer db.Close() 121 122 // Get or create a bucket in the database as needed. This bucket 123 // is what is typically passed to specific sub-packages so they have 124 // their own area to work in without worrying about conflicting keys. 125 bucketKey := []byte("walletsubpackage") 126 err = walletdb.Update(db, func(tx walletdb.ReadWriteTx) error { 127 bucket := tx.ReadWriteBucket(bucketKey) 128 if bucket == nil { 129 _, err = tx.CreateTopLevelBucket(bucketKey) 130 if err != nil { 131 return err 132 } 133 } 134 return nil 135 }) 136 if err != nil { 137 fmt.Println(err) 138 return 139 } 140 141 // Use the Update function of the namespace to perform a managed 142 // read-write transaction. The transaction will automatically be rolled 143 // back if the supplied inner function returns a non-nil error. 144 err = walletdb.Update(db, func(tx walletdb.ReadWriteTx) error { 145 // All data is stored against the root bucket of the namespace, 146 // or nested buckets of the root bucket. It's not really 147 // necessary to store it in a separate variable like this, but 148 // it has been done here for the purposes of the example to 149 // illustrate. 150 rootBucket := tx.ReadWriteBucket(bucketKey) 151 152 // Store a key/value pair directly in the root bucket. 153 key := []byte("mykey") 154 value := []byte("myvalue") 155 if err := rootBucket.Put(key, value); err != nil { 156 return err 157 } 158 159 // Read the key back and ensure it matches. 160 if !bytes.Equal(rootBucket.Get(key), value) { 161 return fmt.Errorf("unexpected value for key '%s'", key) 162 } 163 164 // Create a new nested bucket under the root bucket. 165 nestedBucketKey := []byte("mybucket") 166 nestedBucket, err := rootBucket.CreateBucket(nestedBucketKey) 167 if err != nil { 168 return err 169 } 170 171 // The key from above that was set in the root bucket does not 172 // exist in this new nested bucket. 173 if nestedBucket.Get(key) != nil { 174 return fmt.Errorf("key '%s' is not expected nil", key) 175 } 176 177 return nil 178 }) 179 if err != nil { 180 fmt.Println(err) 181 return 182 } 183 184 // Output: 185 }