// OpenDB creates and opens the database for the block explorer. Sholud be run on startup func openDB(filename string) (*explorerDB, error) { db, err := persist.OpenDatabase(meta, filename) if err != nil { return nil, err } var buckets []string = []string{ "Blocks", "Transactions", "Addresses", "FileContracts", "SiacoinOutputs", "SiafundOutputs", "Heights", "Hashes", } // Create buckets err = db.Update(func(tx *bolt.Tx) error { for _, bucketName := range buckets { _, err := tx.CreateBucketIfNotExists([]byte(bucketName)) if err != nil { return err } } return nil }) if err != nil { return nil, err } return &explorerDB{db}, nil }
// openDB loads the set database and populates it with the necessary buckets func (cs *ConsensusSet) openDB(filename string) (err error) { cs.db, err = persist.OpenDatabase(dbMetadata, filename) if err == persist.ErrBadVersion { return cs.replaceDatabase(filename) } if err != nil { return errors.New("error opening consensus database: " + err.Error()) } return nil }
// initPersist creates buckets in the database func (tp *TransactionPool) initPersist() error { // Create the persist directory if it does not yet exist. err := os.MkdirAll(tp.persistDir, 0700) if err != nil { return err } // Open the database file. tp.db, err = persist.OpenDatabase(dbMetadata, filepath.Join(tp.persistDir, dbFilename)) if err != nil { return err } // Create the database and get the most recent consensus change. var cc modules.ConsensusChangeID err = tp.db.Update(func(tx *bolt.Tx) error { // Create the database buckets. buckets := [][]byte{ bucketRecentConsensusChange, bucketConfirmedTransactions, } for _, bucket := range buckets { _, err := tx.CreateBucketIfNotExists(bucket) if err != nil { return err } } // Get the recent consensus change. cc, err = tp.getRecentConsensusChange(tx) if err == errNilConsensusChange { return tp.putRecentConsensusChange(tx, modules.ConsensusChangeBeginning) } return err }) if err != nil { return err } // Subscribe to the consensus set using the most recent consensus change. err = tp.consensusSet.ConsensusSetSubscribe(tp, cc) if err == modules.ErrInvalidConsensusChangeID { // Reset and rescan because the consensus set does not recognize the // provided consensus change id. resetErr := tp.db.Update(func(tx *bolt.Tx) error { return tp.resetDB(tx) }) if resetErr != nil { return resetErr } return tp.consensusSet.ConsensusSetSubscribe(tp, modules.ConsensusChangeBeginning) } return err }
// replaceDatabase backs up the existing database and creates a new one. func (cs *ConsensusSet) replaceDatabase(filename string) error { // Rename the existing database and create a new one. fmt.Println("Outdated consensus database... backing up and replacing") err := os.Rename(filename, filename+".bck") if err != nil { return errors.New("error while backing up consensus database: " + err.Error()) } // Try again to create a new database, this time without checking for an // outdated database error. cs.db, err = persist.OpenDatabase(dbMetadata, filename) if err != nil { return errors.New("error opening consensus database: " + err.Error()) } return nil }
// openDB loads the set database and populates it with the necessary buckets func openDB(filename string) (*setDB, error) { db, err := persist.OpenDatabase(meta, filename) if err != nil { return nil, err } // Enumerate the database buckets. buckets := [][]byte{ BlockPath, BlockMap, SiacoinOutputs, FileContracts, FileContractExpirations, SiafundOutputs, SiafundPool, DSCOBuckets, } // Initialize the database. err = db.Update(func(tx *bolt.Tx) error { // Create the database buckets. for _, bucket := range buckets { _, err := tx.CreateBucketIfNotExists(bucket) if err != nil { return err } } // Initilize the consistency guards. cg, err := tx.CreateBucketIfNotExists(ConsistencyGuard) if err != nil { return err } gs := cg.Get(GuardStart) ge := cg.Get(GuardEnd) // Database is consistent if both are nil, or if both are equal. // Database is inconsistent otherwise. if (gs != nil && ge != nil && bytes.Equal(gs, ge)) || gs == nil && ge == nil { cg.Put(GuardStart, encoding.EncUint64(1)) cg.Put(GuardEnd, encoding.EncUint64(1)) return nil } return errDBInconsistent }) return &setDB{db, true}, err }
// openDatabase creates a database that the host can use to interact with large // volumes of persistent data. func (productionDependencies) openDatabase(m persist.Metadata, s string) (*persist.BoltDatabase, error) { return persist.OpenDatabase(m, s) }
// TestRescan triggers a rescan in the transaction pool, verifying that the // rescan code does not cause deadlocks or crashes. func TestRescan(t *testing.T) { if testing.Short() { t.SkipNow() } tpt, err := createTpoolTester("TestRescan") if err != nil { t.Fatal(err) } defer tpt.Close() // Create a valid transaction set using the wallet. txns, err := tpt.wallet.SendSiacoins(types.NewCurrency64(100), types.UnlockHash{}) if err != nil { t.Fatal(err) } if len(tpt.tpool.transactionSets) != 1 { t.Error("sending coins did not increase the transaction sets by 1") } // Mine the transaction into a block, so that it's in the consensus set. _, err = tpt.miner.AddBlock() if err != nil { t.Fatal(err) } // Close the tpool, delete the persistence, then restart the tpool. The // tpool should still recognize the transaction set as a duplicate. persistDir := tpt.tpool.persistDir err = tpt.tpool.Close() if err != nil { t.Fatal(err) } err = os.RemoveAll(persistDir) if err != nil { t.Fatal(err) } tpt.tpool, err = New(tpt.cs, tpt.gateway, persistDir) if err != nil { t.Fatal(err) } err = tpt.tpool.AcceptTransactionSet(txns) if err != modules.ErrDuplicateTransactionSet { t.Fatal("expecting modules.ErrDuplicateTransactionSet, got:", err) } // Close the tpool, corrupt the database, then restart the tpool. The tpool // should still recognize the transaction set as a duplicate. err = tpt.tpool.Close() if err != nil { t.Fatal(err) } db, err := persist.OpenDatabase(dbMetadata, filepath.Join(persistDir, dbFilename)) if err != nil { t.Fatal(err) } err = db.Update(func(tx *bolt.Tx) error { ccBytes := tx.Bucket(bucketRecentConsensusChange).Get(fieldRecentConsensusChange) // copy the bytes due to bolt's mmap. newCCBytes := make([]byte, len(ccBytes)) copy(newCCBytes, ccBytes) newCCBytes[0]++ return tx.Bucket(bucketRecentConsensusChange).Put(fieldRecentConsensusChange, newCCBytes) }) if err != nil { t.Fatal(err) } err = db.Close() if err != nil { t.Fatal(err) } tpt.tpool, err = New(tpt.cs, tpt.gateway, persistDir) if err != nil { t.Fatal(err) } err = tpt.tpool.AcceptTransactionSet(txns) if err != modules.ErrDuplicateTransactionSet { t.Fatal("expecting modules.ErrDuplicateTransactionSet, got:", err) } }
// openDB loads the set database and populates it with the necessary buckets func (cs *ConsensusSet) openDB(filename string) (err error) { cs.db, err = persist.OpenDatabase(dbMetadata, filename) return err }
// initPersist initializes the persistent structures of the explorer module. func (e *Explorer) initPersist() error { // Make the persist directory err := os.MkdirAll(e.persistDir, 0700) if err != nil { return err } // Open the database db, err := persist.OpenDatabase(explorerMetadata, filepath.Join(e.persistDir, "explorer.db")) if err != nil { return err } e.db = db // Initialize the database err = e.db.Update(func(tx *bolt.Tx) error { buckets := [][]byte{ bucketBlockFacts, bucketBlockIDs, bucketBlocksDifficulty, bucketBlockTargets, bucketFileContractHistories, bucketFileContractIDs, bucketInternal, bucketSiacoinOutputIDs, bucketSiacoinOutputs, bucketSiafundOutputIDs, bucketSiafundOutputs, bucketTransactionIDs, bucketUnlockHashes, } for _, b := range buckets { _, err := tx.CreateBucketIfNotExists(b) if err != nil { return err } } // set default values for the bucketInternal internalDefaults := []struct { key, val []byte }{ {internalBlockHeight, encoding.Marshal(types.BlockHeight(0))}, {internalRecentChange, encoding.Marshal(modules.ConsensusChangeID{})}, } b := tx.Bucket(bucketInternal) for _, d := range internalDefaults { if b.Get(d.key) != nil { continue } err := b.Put(d.key, d.val) if err != nil { return err } } return nil }) if err != nil { return err } return nil }