example_test.go raw

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