misc: export more functions, make save/load to db default.

This commit is contained in:
Tzu-Jung Lee 2018-08-14 19:50:42 -07:00
parent 372cd7a72f
commit feebb96caa
7 changed files with 132 additions and 110 deletions

View file

@ -47,7 +47,8 @@ func (c *Claim) expireAt() Height {
return c.Accepted + paramOriginalClaimExpirationTime
}
func isActiveAt(c *Claim, ht Height) bool {
// IsActiveAt ...
func IsActiveAt(c *Claim, ht Height) bool {
return c != nil && c.ActiveAt <= ht && c.expireAt() > ht
}

View file

@ -1,22 +1,22 @@
package claim
type list []*Claim
type List []*Claim
type comparator func(c *Claim) bool
type Comparator func(c *Claim) bool
func byOP(op OutPoint) comparator {
func ByOP(op OutPoint) Comparator {
return func(c *Claim) bool {
return c.OutPoint == op
}
}
func byID(id ID) comparator {
func ByID(id ID) Comparator {
return func(c *Claim) bool {
return c.ID == id
}
}
func remove(l list, cmp comparator) (list, *Claim) {
func Remove(l List, cmp Comparator) (List, *Claim) {
last := len(l) - 1
for i, v := range l {
if !cmp(v) {
@ -30,7 +30,7 @@ func remove(l list, cmp comparator) (list, *Claim) {
return l, nil
}
func find(cmp comparator, lists ...list) *Claim {
func Find(cmp Comparator, lists ...List) *Claim {
for _, l := range lists {
for _, v := range l {
if cmp(v) {

View file

@ -16,11 +16,11 @@ type Node struct {
best *Claim
tookover Height
claims list
supports list
claims List
supports List
// refer to updateClaim.
removed list
removed List
}
// NewNode returns a new Node.
@ -28,6 +28,11 @@ func NewNode(name string) *Node {
return &Node{name: name}
}
// Name returns the Name where the Node blongs.
func (n *Node) Name() string {
return n.name
}
// Height returns the current height.
func (n *Node) Height() Height {
return n.height
@ -38,15 +43,30 @@ func (n *Node) BestClaim() *Claim {
return n.best
}
// Tookover returns the the height at when the current BestClaim tookover.
func (n *Node) Tookover() Height {
return n.tookover
}
// Claims returns the claims at the current height.
func (n *Node) Claims() List {
return n.claims
}
// Supports returns the supports at the current height.
func (n *Node) Supports() List {
return n.supports
}
// AddClaim adds a Claim to the Node.
func (n *Node) AddClaim(op OutPoint, amt Amount) error {
if find(byOP(op), n.claims, n.supports) != nil {
func (n *Node) AddClaim(op OutPoint, amt Amount, val []byte) error {
if Find(ByOP(op), n.claims, n.supports) != nil {
return ErrDuplicate
}
accepted := n.height + 1
c := New(op, amt).setID(NewID(op)).setAccepted(accepted)
c := New(op, amt).setID(NewID(op)).setAccepted(accepted).setValue(val)
c.setActiveAt(accepted + calDelay(accepted, n.tookover))
if !isActiveAt(n.best, accepted) {
if !IsActiveAt(n.best, accepted) {
c.setActiveAt(accepted)
n.best, n.tookover = c, accepted
}
@ -57,7 +77,7 @@ func (n *Node) AddClaim(op OutPoint, amt Amount) error {
// SpendClaim spends a Claim in the Node.
func (n *Node) SpendClaim(op OutPoint) error {
var c *Claim
if n.claims, c = remove(n.claims, byOP(op)); c == nil {
if n.claims, c = Remove(n.claims, ByOP(op)); c == nil {
return ErrNotFound
}
n.removed = append(n.removed, c)
@ -74,17 +94,17 @@ func (n *Node) SpendClaim(op OutPoint) error {
//
// For each block, all the spent claims are kept in n.removed until committed.
// The paired (spend, update) commands has to happen in the same trasaction.
func (n *Node) UpdateClaim(op OutPoint, amt Amount, id ID) error {
if find(byOP(op), n.claims, n.supports) != nil {
func (n *Node) UpdateClaim(op OutPoint, amt Amount, id ID, val []byte) error {
if Find(ByOP(op), n.claims, n.supports) != nil {
return ErrDuplicate
}
var c *Claim
if n.removed, c = remove(n.removed, byID(id)); c == nil {
if n.removed, c = Remove(n.removed, ByID(id)); c == nil {
return errors.Wrapf(ErrNotFound, "remove(n.removed, byID(%s)", id)
}
accepted := n.height + 1
c.setOutPoint(op).setAmt(amt).setAccepted(accepted)
c.setOutPoint(op).setAmt(amt).setAccepted(accepted).setValue(val)
c.setActiveAt(accepted + calDelay(accepted, n.tookover))
if n.best != nil && n.best.ID == id {
c.setActiveAt(n.tookover)
@ -95,12 +115,12 @@ func (n *Node) UpdateClaim(op OutPoint, amt Amount, id ID) error {
// AddSupport adds a Support to the Node.
func (n *Node) AddSupport(op OutPoint, amt Amount, id ID) error {
if find(byOP(op), n.claims, n.supports) != nil {
if Find(ByOP(op), n.claims, n.supports) != nil {
return ErrDuplicate
}
// Accepted by rules. No effects on bidding result though.
// It may be spent later.
if find(byID(id), n.claims, n.removed) == nil {
if Find(ByID(id), n.claims, n.removed) == nil {
// fmt.Printf("INFO: can't find suooported claim ID: %s for %s\n", id, n.name)
}
@ -117,7 +137,7 @@ func (n *Node) AddSupport(op OutPoint, amt Amount, id ID) error {
// SpendSupport spends a support in the Node.
func (n *Node) SpendSupport(op OutPoint) error {
var s *Claim
if n.supports, s = remove(n.supports, byOP(op)); s != nil {
if n.supports, s = Remove(n.supports, ByOP(op)); s != nil {
return nil
}
return ErrNotFound
@ -147,7 +167,7 @@ func (n *Node) AdjustTo(ht Height) *Node {
// When no pending updates exist, current height is returned.
func (n *Node) NextUpdate() Height {
next := Height(math.MaxInt32)
min := func(l list) Height {
min := func(l List) Height {
for _, v := range l {
exp := v.expireAt()
if n.height >= exp {
@ -187,15 +207,15 @@ func (n *Node) bid() {
n.removed = nil
}
func updateEffectiveAmounts(ht Height, claims, supports list) {
func updateEffectiveAmounts(ht Height, claims, supports List) {
for _, c := range claims {
c.EffAmt = 0
if !isActiveAt(c, ht) {
if !IsActiveAt(c, ht) {
continue
}
c.EffAmt = c.Amt
for _, s := range supports {
if !isActiveAt(s, ht) || s.ID != c.ID {
if !IsActiveAt(s, ht) || s.ID != c.ID {
continue
}
c.EffAmt += s.Amt
@ -203,7 +223,7 @@ func updateEffectiveAmounts(ht Height, claims, supports list) {
}
}
func updateActiveHeights(n *Node, lists ...list) {
func updateActiveHeights(n *Node, lists ...List) {
for _, l := range lists {
for _, v := range l {
v.ActiveAt = v.Accepted + calDelay(n.height, n.tookover)
@ -211,11 +231,11 @@ func updateActiveHeights(n *Node, lists ...list) {
}
}
func findCandiadte(ht Height, claims list) *Claim {
func findCandiadte(ht Height, claims List) *Claim {
var c *Claim
for _, v := range claims {
switch {
case !isActiveAt(v, ht):
case !IsActiveAt(v, ht):
continue
case c == nil:
c = v

View file

@ -17,8 +17,8 @@ func export(n *Node) interface{} {
Tookover Height
NextUpdate Height
BestClaim *Claim
Claims list
Supports list
Claims List
Supports List
}{
Height: n.height,
Hash: hash,

View file

@ -3,6 +3,7 @@ package claimtrie
import (
"fmt"
"github.com/lbryio/claimtrie/cfg"
"github.com/lbryio/claimtrie/change"
"github.com/lbryio/claimtrie/claim"
"github.com/lbryio/claimtrie/nodemgr"
@ -18,41 +19,71 @@ type ClaimTrie struct {
cm *CommitMgr
nm *nodemgr.NodeMgr
tr *trie.Trie
cleanup func() error
}
// New returns a ClaimTrie.
func New(dbCommit, dbTrie, dbNodeMgr *leveldb.DB) *ClaimTrie {
nm := nodemgr.New(dbNodeMgr)
cm := NewCommitMgr(dbCommit)
func New() (*ClaimTrie, error) {
path := cfg.DefaultConfig(cfg.TrieDB)
dbTrie, err := leveldb.OpenFile(path, nil)
if err != nil {
return nil, errors.Wrapf(err, "can't open %s", path)
}
return &ClaimTrie{
path = cfg.DefaultConfig(cfg.NodeDB)
dbNodeMgr, err := leveldb.OpenFile(path, nil)
if err != nil {
return nil, errors.Wrapf(err, "can't open %s", path)
}
path = cfg.DefaultConfig(cfg.CommitDB)
dbCommit, err := leveldb.OpenFile(path, nil)
if err != nil {
return nil, errors.Wrapf(err, "can't open %s", path)
}
cm := NewCommitMgr(dbCommit)
if err := cm.Load(); err != nil {
return nil, errors.Wrapf(err, "cm.Load()")
}
fmt.Printf("%d of commits loaded. Head: %d\n", len(cm.commits), cm.head.Meta.Height)
nm := nodemgr.New(dbNodeMgr)
nm.Load(cm.head.Meta.Height)
fmt.Printf("%d of nodes loaded.\n", nm.Size())
tr := trie.New(nm, dbTrie)
tr.SetRoot(cm.Head().MerkleRoot)
fmt.Printf("ClaimTrie Root: %s.\n", tr.MerkleHash())
ct := &ClaimTrie{
cm: cm,
nm: nm,
tr: trie.New(nm, dbTrie),
tr: tr,
cleanup: func() error {
if err := cm.Save(); err != nil {
return errors.Wrapf(err, "cm.Save()")
}
if err := dbTrie.Close(); err != nil {
return errors.Wrapf(err, "dbTrie.Close()")
}
if err := dbNodeMgr.Close(); err != nil {
return errors.Wrapf(err, "dbNodeMgr.Close()")
}
if err := dbCommit.Close(); err != nil {
return errors.Wrapf(err, "dbCommit.Close()")
}
return nil
},
}
return ct, nil
}
// Load loads ClaimTrie, NodeManager, Trie from databases.
func (ct *ClaimTrie) Load() error {
if err := ct.cm.Load(); err != nil {
return errors.Wrapf(err, "cm.Load()")
}
fmt.Printf("%d of commits loaded. Head: %d\n", len(ct.cm.commits), ct.cm.head.Meta.Height)
ct.nm.Load(ct.Height())
fmt.Printf("%d of nodes loaded.\n", ct.nm.Size())
ct.tr.SetRoot(ct.cm.Head().MerkleRoot)
fmt.Printf("Trie root: %s.\n", ct.MerkleHash())
return nil
}
// Save saves ClaimTrie state to database.
func (ct *ClaimTrie) Save() error {
if err := ct.cm.Save(); err != nil {
return errors.Wrapf(err, "cm.Save()")
}
return nil
// Close saves ClaimTrie state to database.
func (ct *ClaimTrie) Close() error {
return ct.cleanup()
}
// Height returns the highest height of blocks commited to the ClaimTrie.

View file

@ -149,22 +149,6 @@ func main() {
Action: cmdImport,
Flags: []cli.Flag{flagHeight, flagCheck, flagVerbose},
},
{
Name: "load",
Aliases: []string{"ld"},
Usage: "Load nodes from datbase.",
Before: parseArgs,
Action: cmdLoad,
Flags: []cli.Flag{},
},
{
Name: "save",
Aliases: []string{"sv"},
Usage: "Save nodes to datbase.",
Before: parseArgs,
Action: cmdSave,
Flags: []cli.Flag{},
},
{
Name: "erase",
Usage: "Erase datbase",
@ -181,28 +165,10 @@ func main() {
},
}
path := cfg.DefaultConfig(cfg.TrieDB)
dbTrie, err := leveldb.OpenFile(path, nil)
if err != nil {
log.Fatalf("can't open %s, err: %s\n", path, err)
var err error
if ct, err = claimtrie.New(); err != nil {
log.Fatalf("can'y create ClaimTrie, err: %s", err)
}
fmt.Printf("opened %q\n", path)
path = cfg.DefaultConfig(cfg.NodeDB)
dbNodeMgr, err := leveldb.OpenFile(path, nil)
if err != nil {
log.Fatalf("can't open %s, err: %s\n", path, err)
}
fmt.Printf("opened %q\n", path)
path = cfg.DefaultConfig(cfg.CommitDB)
dbCommit, err := leveldb.OpenFile(path, nil)
if err != nil {
log.Fatalf("can't open %s, err: %s\n", path, err)
}
fmt.Printf("opened %q\n", path)
ct = claimtrie.New(dbCommit, dbTrie, dbNodeMgr)
if err := app.Run(os.Args); err != nil {
fmt.Printf("error: %s\n", err)
}
@ -283,14 +249,6 @@ func cmdImport(c *cli.Context) error {
return nil
}
func cmdLoad(c *cli.Context) error {
return ct.Load()
}
func cmdSave(c *cli.Context) error {
return ct.Save()
}
func cmdErase(c *cli.Context) error {
if err := os.RemoveAll(cfg.DefaultConfig(cfg.CommitDB)); err != nil {
return err
@ -329,8 +287,8 @@ func cmdShell(app *cli.App) {
continue
}
if text == "quit" || text == "q" {
if err = ct.Save(); err != nil {
fmt.Printf("ct.Save() failed, err: %s\n", err)
if err = ct.Close(); err != nil {
fmt.Printf("ct.Close() failed, err: %s\n", err)
}
break
}

View file

@ -43,7 +43,7 @@ func (nm *NodeMgr) Load(ht claim.Height) {
// Get returns the latest node with name specified by key.
func (nm *NodeMgr) Get(key []byte) trie.Value {
return nm.nodeAt(string(key), nm.height)
return nm.NodeAt(string(key), nm.height)
}
// Reset resets all nodes to specified height.
@ -66,8 +66,8 @@ func (nm *NodeMgr) load(name string, ht claim.Height) *claim.Node {
return NewFromChanges(name, c, ht)
}
// nodeAt returns the node adjusted to specified height.
func (nm *NodeMgr) nodeAt(name string, ht claim.Height) *claim.Node {
// NodeAt returns the node adjusted to specified height.
func (nm *NodeMgr) NodeAt(name string, ht claim.Height) *claim.Node {
n, ok := nm.cache[name]
if !ok {
n = claim.NewNode(name)
@ -84,7 +84,7 @@ func (nm *NodeMgr) nodeAt(name string, ht claim.Height) *claim.Node {
// ModifyNode returns the node adjusted to specified height.
func (nm *NodeMgr) ModifyNode(name string, chg *change.Change) error {
ht := nm.height
n := nm.nodeAt(name, ht)
n := nm.NodeAt(name, ht)
n.AdjustTo(ht)
if err := execute(n, chg); err != nil {
return errors.Wrapf(err, "claim.execute(n,chg)")
@ -100,12 +100,24 @@ func (nm *NodeMgr) CatchUp(ht claim.Height, notifier func(key []byte)) {
nm.height = ht
for name := range nm.nextUpdates[ht] {
notifier([]byte(name))
if next := nm.nodeAt(name, ht).NextUpdate(); next > ht {
if next := nm.NodeAt(name, ht).NextUpdate(); next > ht {
nm.nextUpdates.set(name, next)
}
}
}
// VisitFunc ...
type VisitFunc func(n *claim.Node) (stop bool)
// Visit visits every node in the cache with VisiFunc.
func (nm *NodeMgr) Visit(v VisitFunc) {
for _, n := range nm.cache {
if v(n) {
return
}
}
}
// Show is a conevenient function for debugging and velopment purpose.
// The proper way to handle user request would be a query function with filters specified.
func (nm *NodeMgr) Show(name string, ht claim.Height, dump bool) error {
@ -119,7 +131,7 @@ func (nm *NodeMgr) Show(name string, ht claim.Height, dump bool) error {
}
sort.Strings(names)
for _, name := range names {
n := nm.nodeAt(name, ht)
n := nm.NodeAt(name, ht)
if n.BestClaim() == nil {
continue
}