// applyFileContractMaintenance looks for all of the file contracts that have // expired without an appropriate storage proof, and calls 'applyMissedProof' // for the file contract. func applyFileContractMaintenance(tx *bolt.Tx, pb *processedBlock) { // Get the bucket pointing to all of the expiring file contracts. fceBucketID := append(prefixFCEX, encoding.Marshal(pb.Height)...) fceBucket := tx.Bucket(fceBucketID) // Finish if there are no expiring file contracts. if fceBucket == nil { return } var dscods []modules.DelayedSiacoinOutputDiff var fcds []modules.FileContractDiff err := fceBucket.ForEach(func(keyBytes, valBytes []byte) error { var id types.FileContractID copy(id[:], keyBytes) amspDSCODS, fcd := applyMissedStorageProof(tx, pb, id) fcds = append(fcds, fcd) dscods = append(dscods, amspDSCODS...) return nil }) if build.DEBUG && err != nil { panic(err) } for _, dscod := range dscods { pb.DelayedSiacoinOutputDiffs = append(pb.DelayedSiacoinOutputDiffs, dscod) commitDelayedSiacoinOutputDiff(tx, dscod, modules.DiffApply) } for _, fcd := range fcds { pb.FileContractDiffs = append(pb.FileContractDiffs, fcd) commitFileContractDiff(tx, fcd, modules.DiffApply) } err = tx.DeleteBucket(fceBucketID) if build.DEBUG && err != nil { panic(err) } }
func (n *node) drop(tx *bolt.Tx, bucketName string) error { bucket := n.GetBucket(tx) if bucket == nil { return tx.DeleteBucket([]byte(bucketName)) } return bucket.DeleteBucket([]byte(bucketName)) }
func delete(tx *bolt.Tx, hash, kw, kh []byte) error { bimg := tx.Bucket([]byte(images)) bhits := tx.Bucket([]byte(hits)) w := bimg.Get(hash) if w == nil { return e.New(ErrImageNotFound) } bw := tx.Bucket(append(hash, w...)) if bw == nil { return e.New(ErrImageNotFound) } h := bw.Get(kw) if h == nil { return e.New(ErrImageNotFound) } bh := tx.Bucket([]byte(string(hash) + string(w) + string(h))) if bh == nil { return e.New(ErrImageNotFound) } err := bh.Delete(kh) if err != nil { return e.Forward(err) } if bh.Stats().KeyN <= 0 { err = tx.DeleteBucket([]byte(string(hash) + string(w) + string(h))) if err != nil { return e.Forward(err) } err = bw.Delete(kw) if err != nil { return e.Forward(err) } if bw.Stats().KeyN <= 0 { err = tx.DeleteBucket(append(hash, w...)) if err != nil { return e.Forward(err) } err = bimg.Delete(hash) if err != nil { return e.Forward(err) } } } // BUG: FAULT ADDRS hitshash := append(hash, append(kw, kh...)...) err = bhits.Delete(hitshash) if err != nil { return e.Forward(err) } return nil }
func removeDSCOBucket(tx *bolt.Tx, bh types.BlockHeight) error { bhBytes := encoding.EncUint64(uint64(bh)) bucketID := append(prefix_dsco, bhBytes...) err := tx.DeleteBucket(bucketID) if err != nil { return err } b := tx.Bucket(DSCOBuckets) if build.DEBUG && b.Get(bhBytes) == nil { panic(errNilItem) } return b.Delete(bhBytes) }
// deleteDSCOBucket deletes the bucket that held a set of delayed siacoin // outputs. func deleteDSCOBucket(tx *bolt.Tx, bh types.BlockHeight) { // Delete the bucket. bucketID := append(prefixDSCO, encoding.Marshal(bh)...) bucket := tx.Bucket(bucketID) if build.DEBUG && bucket == nil { panic(errNilBucket) } // TODO: Check that the bucket is empty. Using Stats() does not work at the // moment, as there is an error in the boltdb code. err := tx.DeleteBucket(bucketID) if build.DEBUG && err != nil { panic(err) } }
// refreshDB saves, deletes, and then restores all of the buckets in the // database. This eliminates bugs during reorgs. The exact source of the bugs // is unknown, but the problem is that after excessive use by Sia, calling // Delete on a bucket will occasionally delete many more elements than the // single element being targeted. It is strongly suspected that this is due to // an error in the boltdb code, but the source remains unknown for the time // being. Refreshing the database between blocks has solved the issue for the // time being - it is currently unknown whether large blocks are able to // trigger the error, but it is suspected that large blocks are safe. func refreshDB(tx *bolt.Tx) { // Get a list of buckets. var bucketNames [][]byte err := tx.ForEach(func(bucketName []byte, _ *bolt.Bucket) error { bucketNames = append(bucketNames, bucketName) return nil }) if err != nil { manageErr(tx, err) } for _, bucketName := range bucketNames { var keys [][]byte var values [][]byte err := tx.Bucket(bucketName).ForEach(func(k, v []byte) error { keys = append(keys, k) values = append(values, v) return nil }) if err != nil { manageErr(tx, err) } err = tx.DeleteBucket(bucketName) if err != nil { manageErr(tx, err) } bucket, err := tx.CreateBucket(bucketName) if err != nil { manageErr(tx, err) } for i := range keys { err := bucket.Put(keys[i], values[i]) if err != nil { manageErr(tx, err) } } } }
func Del(tx *bolt.Tx, bucket []byte, keys [][]byte) error { if len(keys) == 0 { return e.New("no keys") } bname := make([][]byte, len(keys)) bs := make([]*bolt.Bucket, len(keys)) b := tx.Bucket(bucket) bname[0] = bucket bs[0] = b for i := 0; i < len(keys); i++ { v := b.Get(keys[i]) b = tx.Bucket(v) if i+1 < len(keys) { bname[i+1] = v bs[i+1] = b } } for level := len(bs) - 1; level >= 0; level-- { err := bs[level].Delete(keys[level]) if err != nil { return e.Forward(err) } if bs[level].Stats().KeyN <= 1 { if level-1 < 0 { break } err = tx.DeleteBucket(bname[level]) if err != nil { return e.Forward(err) } continue } break } return nil }