func hasNodeInTable(datfile string, n *node.Node) bool {
	var r bool
	err := db.DB.View(func(tx *bolt.Tx) error {
		r = db.HasVal(tx, "lookupT", []byte(datfile), n.Nodestr)
		return nil
	})
	if err != nil {
		log.Println(err)
	}
	return r
}
hasNodeInTable returns true if nodelist has n.
package manager
import (
	"errors"
	"log"
	"math/rand"
	"strconv"
	"strings"
	"sync"
	"github.com/boltdb/bolt"
	"github.com/shingetsu-gou/shingetsu-gou/cfg"
	"github.com/shingetsu-gou/shingetsu-gou/db"
	"github.com/shingetsu-gou/shingetsu-gou/myself"
	"github.com/shingetsu-gou/shingetsu-gou/node"
)
const (
	defaultNodes = 100  
	shareNodes   = 100  
)
var list = string([]byte{0x01})
func getFromList() *node.Node {
	var rs map[string]struct{}
	err := db.DB.View(func(tx *bolt.Tx) error {
		var err error
		rs, err = db.GetMap(tx, "lookupT", []byte(list))
		return err
	})
	if err != nil {
		log.Print(err)
		return nil
	}
	if len(rs) == 0 {
		log.Println("node not found")
		return nil
	}
	var r string
	for rr := range rs {
		r = rr
		break
	}
	n, err := node.New(r)
	if err != nil {
		log.Println(err)
		return nil
	}
	return n
}
func NodeLen() int {
	ns := getAllNodes()
	return ns.Len()
}
func ListLen() int {
	return listLen(list)
}
func listLen(datfile string) int {
	var rs map[string]struct{}
	err := db.DB.View(func(tx *bolt.Tx) error {
		var err error
		rs, err = db.GetMap(tx, "lookupT", []byte(datfile))
		return err
	})
	if err != nil {
		log.Print(err, datfile)
		return 0
	}
	return len(rs)
}
func GetNodestrSlice() []string {
	return getAllNodes().GetNodestrSlice()
}
func getAllNodes() node.Slice {
	var r []string
	err := db.DB.View(func(tx *bolt.Tx) error {
		var err error
		r, err = db.KeyStrings(tx, "lookupA")
		return err
	})
	if err != nil {
		log.Print(err)
		return nil
	}
	return node.NewSlice(r)
}
func Get(datfile string, def node.Slice) node.Slice {
	str := GetNodestrSliceInTable(datfile)
	if str == nil {
		return def
	}
	return node.NewSlice(str)
}
func GetNodestrSliceInList() []string {
	return GetNodestrSliceInTable(list)
}
func GetNodestrSliceInTable(datfile string) []string {
	var r []string
	err := db.DB.View(func(tx *bolt.Tx) error {
		var err error
		r, err = db.MapKeys(tx, "lookupT", []byte(datfile))
		return err
	})
	if err != nil {
		log.Print(err, datfile)
		return nil
	}
	return r
}
func Random(exclude node.Slice, num int) []*node.Node {
	all := getAllNodes()
	if exclude != nil {
		cand := make([]*node.Node, 0, len(all))
		m := exclude.ToMap()
		for _, n := range all {
			if _, exist := m[n.Nodestr]; !exist {
				cand = append(cand, n)
			}
		}
		all = cand
	}
	n := all.Len()
	if num < n && num != 0 {
		n = num
	}
	r := make([]*node.Node, n)
	rs := rand.Perm(all.Len())
	for i := 0; i < n; i++ {
		r[i] = all[rs[i]]
	}
	return r
}
func appendable(datfile string, n *node.Node) bool {
	l := listLen(datfile)
	return ((datfile != "" && l < shareNodes) ||
		(datfile == "" && l < defaultNodes)) &&
		n != nil && n.IsAllowed() && !hasNodeInTable(datfile, n)
}
func AppendToTable(datfile string, n *node.Node) {
	err := db.DB.Update(func(tx *bolt.Tx) error {
		AppendToTableTX(tx, datfile, n)
		return nil
	})
	if err != nil {
		log.Println(err)
	}
}
func AppendToTableTX(tx *bolt.Tx, datfile string, n *node.Node) {
	if !appendable(datfile, n) {
		return
	}
	err := db.PutMap(tx, "lookupT", []byte(datfile), n.Nodestr)
	if err != nil {
		log.Print(err)
	}
	err = db.PutMap(tx, "lookupA", []byte(n.Nodestr), datfile)
	if err != nil {
		log.Print(err)
	}
}
func AppendToList(n *node.Node) {
	AppendToTable(list, n)
}
func appendToList(tx *bolt.Tx, n *node.Node) {
	AppendToTableTX(tx, list, n)
}
func ReplaceNodeInList(n *node.Node) *node.Node {
	l := ListLen()
	if !n.IsAllowed() || hasNodeInTable(list, n) {
		return nil
	}
	var old *node.Node
	if l >= defaultNodes {
		old = getFromList()
		RemoveFromList(old)
		old.Bye()
	}
	err := db.DB.Update(func(tx *bolt.Tx) error {
		appendToList(tx, n)
		return nil
	})
	if err != nil {
		log.Println(err)
	}
	return old
}