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  }