github.com/lbryio/lbcd@v0.22.119/database/example_test.go (about) 1 // Copyright (c) 2015-2016 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 database_test 6 7 import ( 8 "bytes" 9 "fmt" 10 "os" 11 "path/filepath" 12 13 "github.com/lbryio/lbcd/chaincfg" 14 "github.com/lbryio/lbcd/database" 15 _ "github.com/lbryio/lbcd/database/ffldb" 16 "github.com/lbryio/lbcd/wire" 17 btcutil "github.com/lbryio/lbcutil" 18 ) 19 20 // This example demonstrates creating a new database. 21 func ExampleCreate() { 22 // This example assumes the ffldb driver is imported. 23 // 24 // import ( 25 // "github.com/lbryio/lbcd/database" 26 // _ "github.com/lbryio/lbcd/database/ffldb" 27 // ) 28 29 // Create a database and schedule it to be closed and removed on exit. 30 // Typically you wouldn't want to remove the database right away like 31 // this, nor put it in the temp directory, but it's done here to ensure 32 // the example cleans up after itself. 33 dbPath := filepath.Join(os.TempDir(), "examplecreate") 34 db, err := database.Create("ffldb", dbPath, wire.MainNet) 35 if err != nil { 36 fmt.Println(err) 37 return 38 } 39 defer os.RemoveAll(dbPath) 40 defer db.Close() 41 42 // Output: 43 } 44 45 // This example demonstrates creating a new database and using a managed 46 // read-write transaction to store and retrieve metadata. 47 func Example_basicUsage() { 48 // This example assumes the ffldb driver is imported. 49 // 50 // import ( 51 // "github.com/lbryio/lbcd/database" 52 // _ "github.com/lbryio/lbcd/database/ffldb" 53 // ) 54 55 // Create a database and schedule it to be closed and removed on exit. 56 // Typically you wouldn't want to remove the database right away like 57 // this, nor put it in the temp directory, but it's done here to ensure 58 // the example cleans up after itself. 59 dbPath := filepath.Join(os.TempDir(), "exampleusage") 60 db, err := database.Create("ffldb", dbPath, wire.MainNet) 61 if err != nil { 62 fmt.Println(err) 63 return 64 } 65 defer os.RemoveAll(dbPath) 66 defer db.Close() 67 68 // Use the Update function of the database to perform a managed 69 // read-write transaction. The transaction will automatically be rolled 70 // back if the supplied inner function returns a non-nil error. 71 err = db.Update(func(tx database.Tx) error { 72 // Store a key/value pair directly in the metadata bucket. 73 // Typically a nested bucket would be used for a given feature, 74 // but this example is using the metadata bucket directly for 75 // simplicity. 76 key := []byte("mykey") 77 value := []byte("myvalue") 78 if err := tx.Metadata().Put(key, value); err != nil { 79 return err 80 } 81 82 // Read the key back and ensure it matches. 83 if !bytes.Equal(tx.Metadata().Get(key), value) { 84 return fmt.Errorf("unexpected value for key '%s'", key) 85 } 86 87 // Create a new nested bucket under the metadata bucket. 88 nestedBucketKey := []byte("mybucket") 89 nestedBucket, err := tx.Metadata().CreateBucket(nestedBucketKey) 90 if err != nil { 91 return err 92 } 93 94 // The key from above that was set in the metadata bucket does 95 // not exist in this new nested bucket. 96 if nestedBucket.Get(key) != nil { 97 return fmt.Errorf("key '%s' is not expected nil", key) 98 } 99 100 return nil 101 }) 102 if err != nil { 103 fmt.Println(err) 104 return 105 } 106 107 // Output: 108 } 109 110 // This example demonstrates creating a new database, using a managed read-write 111 // transaction to store a block, and using a managed read-only transaction to 112 // fetch the block. 113 func Example_blockStorageAndRetrieval() { 114 // This example assumes the ffldb driver is imported. 115 // 116 // import ( 117 // "github.com/lbryio/lbcd/database" 118 // _ "github.com/lbryio/lbcd/database/ffldb" 119 // ) 120 121 // Create a database and schedule it to be closed and removed on exit. 122 // Typically you wouldn't want to remove the database right away like 123 // this, nor put it in the temp directory, but it's done here to ensure 124 // the example cleans up after itself. 125 dbPath := filepath.Join(os.TempDir(), "exampleblkstorage") 126 db, err := database.Create("ffldb", dbPath, wire.MainNet) 127 if err != nil { 128 fmt.Println(err) 129 return 130 } 131 defer os.RemoveAll(dbPath) 132 defer db.Close() 133 134 // Use the Update function of the database to perform a managed 135 // read-write transaction and store a genesis block in the database as 136 // and example. 137 err = db.Update(func(tx database.Tx) error { 138 genesisBlock := chaincfg.MainNetParams.GenesisBlock 139 return tx.StoreBlock(btcutil.NewBlock(genesisBlock)) 140 }) 141 if err != nil { 142 fmt.Println(err) 143 return 144 } 145 146 // Use the View function of the database to perform a managed read-only 147 // transaction and fetch the block stored above. 148 var loadedBlockBytes []byte 149 err = db.Update(func(tx database.Tx) error { 150 genesisHash := chaincfg.MainNetParams.GenesisHash 151 blockBytes, err := tx.FetchBlock(genesisHash) 152 if err != nil { 153 return err 154 } 155 156 // As documented, all data fetched from the database is only 157 // valid during a database transaction in order to support 158 // zero-copy backends. Thus, make a copy of the data so it 159 // can be used outside of the transaction. 160 loadedBlockBytes = make([]byte, len(blockBytes)) 161 copy(loadedBlockBytes, blockBytes) 162 return nil 163 }) 164 if err != nil { 165 fmt.Println(err) 166 return 167 } 168 169 // Typically at this point, the block could be deserialized via the 170 // wire.MsgBlock.Deserialize function or used in its serialized form 171 // depending on need. However, for this example, just display the 172 // number of serialized bytes to show it was loaded as expected. 173 fmt.Printf("Serialized block size: %d bytes\n", len(loadedBlockBytes)) 174 175 // Output: 176 // Serialized block size: 229 bytes 177 }