The core protocol of WoopChain
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
woop/api/service/metrics/storage.go

102 lines
2.8 KiB

package metrics
import (
"fmt"
"os"
"sync"
"time"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/rlp"
"github.com/harmony-one/harmony/internal/utils"
)
// Constants for storage.
const (
BalancePrefix = "bap"
BlockHeightPrefix = "bhp"
BlocksPrefix = "bp"
BlockRewardPrefix = "brp"
ConnectionsNumberPrefix = "cnp"
ConsensusTimePrefix = "ltp"
IsLeaderPrefix = "ilp"
TxPoolPrefix = "tpp"
)
// GetKey returns key by prefix and pushed time momemnt.
func GetKey(prefix string, moment int64) string {
return fmt.Sprintf("%s_%d", prefix, moment)
}
// storage instance
var storage *Storage
var onceMetrics sync.Once
// Storage storage dump the block info into leveldb.
type Storage struct {
db *ethdb.LDBDatabase
}
// GetStorageInstance returns attack model by using singleton pattern.
func GetStorageInstance(ip, port string, remove bool) *Storage {
onceMetrics.Do(func() {
storage = &Storage{}
storage.Init(ip, port, remove)
})
return storage
}
// Init initializes storage.
func (storage *Storage) Init(ip, port string, remove bool) {
dbFileName := "/tmp/db_metrics_" + ip + "_" + port
var err error
if remove {
var err = os.RemoveAll(dbFileName)
if err != nil {
utils.Logger().Error().Err(err).Msg("Failed to remove existing database files.")
}
}
if storage.db, err = ethdb.NewLDBDatabase(dbFileName, 0, 0); err != nil {
utils.Logger().Error().Err(err).Msg("Failed to create new database.")
}
}
// GetDB returns the LDBDatabase of the storage.
func (storage *Storage) GetDB() *ethdb.LDBDatabase {
return storage.db
}
// Dump data into lvdb by value and prefix.
func (storage *Storage) Dump(value interface{}, prefix string) error {
currentTime := time.Now().UnixNano()
utils.Logger().Info().Msgf("Store %s %v at time %d", prefix, value, currentTime)
batch := storage.db.NewBatch()
// Update database.
if err := batch.Put([]byte(GetKey(prefix, currentTime)), []byte(fmt.Sprintf("%v", value.(interface{})))); err != nil {
utils.Logger().Warn().Err(err).Msgf("Cannot batch %s.", prefix)
return err
}
if err := batch.Write(); err != nil {
utils.Logger().Warn().Err(err).Msg("Cannot write batch.")
return err
}
return nil
}
// Read returns data list of a particular metric by since, until, prefix, interface.
func (storage *Storage) Read(since, until int64, prefix string, varType interface{}) []interface{} {
dataList := make([]interface{}, 0)
for i := since; i <= until; i++ {
data, err := storage.db.Get([]byte(GetKey(prefix, i)))
if err != nil {
continue
}
decodedData := varType
if rlp.DecodeBytes(data, decodedData) != nil {
utils.Logger().Error().Msg("Error on getting data from db.")
os.Exit(1)
}
dataList = append(dataList, decodedData)
}
return dataList
}