package main import log "github.com/sirupsen/logrus" //import "io/ioutil" import "fmt" import "strconv" //steem block fetcher const appPrefix = "sbf" type SteemDataStorer interface { SetCurrentNetworkBlockHeight(BlockNumber) error SetCurrentLocalBlockHeight(BlockNumber) error UpdateCurrentLocalBlockHeight() CurrentLocalBlockHeight() BlockNumber CurrentNetworkBlockHeight() BlockNumber HaveOpsForBlock(BlockNumber) bool StoreBlockOps(BlockNumber, *[]byte) error } // SteemDataStore is the object with which the rest of this tool interacts type SteemDataStore struct { kv KVStorer } func NewSteemDataStore(hostname string) SteemDataStorer { self := new(SteemDataStore) self.kv = NewRedisKVStore(hostname) self.init() return self } func (self *SteemDataStore) init() { self.UpdateCurrentLocalBlockHeight() } func (self *SteemDataStore) UpdateCurrentLocalBlockHeight() { cur := self.CurrentLocalBlockHeight() next := self.FindHighestContiguousBlockInDb(cur) if next != cur { err := self.SetCurrentLocalBlockHeight(next) log.Infof("current highest contig block in db is now %d", next) if err != nil { log.Panic(err) } return } } func (self *SteemDataStore) SetCurrentLocalBlockHeight(blockNum BlockNumber) error { keyname := fmt.Sprintf("%s.meta.CurrentLocalBlockHeight", appPrefix) value := fmt.Sprintf("%d", blockNum) return self.kv.Put(&keyname, &value) } func (self *SteemDataStore) SetCurrentNetworkBlockHeight(blockNum BlockNumber) error { keyname := fmt.Sprintf("%s.meta.CurrentNetworkBlockHeight", appPrefix) value := fmt.Sprintf("%d", blockNum) return self.kv.Put(&keyname, &value) } func (self *SteemDataStore) FindHighestContiguousBlockInDb(from BlockNumber) BlockNumber { last := from var keyname string var try BlockNumber for { try = BlockNumber(uint64(last) + 1) keyname = fmt.Sprintf("%s.ops_in_block.%d", appPrefix, try) exists, err := self.kv.Exists(&keyname) if err != nil { log.Panic(err) } if exists == false { log.Debugf("cannot find block %d in db, highest found is %d", try, last) return last } else { last = try } } } func (self *SteemDataStore) StoreBlockOps(blockNum BlockNumber, blockOps *[]byte) error { keyname := fmt.Sprintf("%s.ops_in_block.%d", appPrefix, blockNum) value := string(*blockOps) return self.kv.Put(&keyname, &value) } func (self *SteemDataStore) HaveOpsForBlock(blockNum BlockNumber) bool { keyname := fmt.Sprintf("%s.ops_in_block.%d", appPrefix, blockNum) exists, _ := self.kv.Exists(&keyname) return exists } func (self *SteemDataStore) CurrentNetworkBlockHeight() BlockNumber { keyname := fmt.Sprintf("%s.meta.CurrentNetworkBlockHeight", appPrefix) val, err := self.kv.Get(&keyname) if err != nil { // assume this is key not found, initialize key to default self.SetCurrentNetworkBlockHeight(0) // retry return self.CurrentNetworkBlockHeight() } intval, err := strconv.ParseUint(*val, 10, 64) return BlockNumber(intval) } func (self *SteemDataStore) CurrentLocalBlockHeight() BlockNumber { keyname := fmt.Sprintf("%s.meta.CurrentLocalBlockHeight", appPrefix) val, err := self.kv.Get(&keyname) if err != nil { // assume this is key not found, initialize key to default self.SetCurrentLocalBlockHeight(0) // retry return self.CurrentLocalBlockHeight() } intval, err := strconv.ParseUint(*val, 10, 64) return BlockNumber(intval) }