func (l *kvLog) get(i uint64) (le replication.LogEntry, err error) {
	dbkey := make([]byte, len(l.prefix)+8)
	copy(dbkey, l.prefix)
	binary.BigEndian.PutUint64(dbkey[len(l.prefix):], i)
	entryBytes, err := l.db.Get(dbkey[:])
	if err != nil {
		return le, err
	}
	return replication.LogEntry{Data: entryBytes}, nil
}
get returns entry number i from l.db
package kvlog
import (
	"encoding/binary"
	"sync"
	"github.com/yahoo/coname/keyserver/kv"
	"github.com/yahoo/coname/keyserver/replication"
	"golang.org/x/net/context"
)
type kvLog struct {
	db         kv.DB
	prefix     []byte
	nextIndex  uint64
	skipBefore uint64
	leaderHintSet chan bool
	propose       chan replication.LogEntry
	waitCommitted chan replication.LogEntry
	stopOnce sync.Once
	stop     chan struct{}
	stopped  chan struct{}
}
var _ replication.LogReplicator = (*kvLog)(nil)
func New(db kv.DB, prefix []byte) (replication.LogReplicator, error) {
	nextIndex := uint64(0)
	iter := db.NewIterator(kv.BytesPrefix(prefix))
	if hasEntries := iter.Last(); hasEntries {
		nextIndex = binary.BigEndian.Uint64(iter.Key()[len(prefix):]) + 1
	}
	iter.Release()
	if err := iter.Error(); err != nil {
		return nil, err
	}
	leaderHintSet := make(chan bool, 1)
	leaderHintSet <- true
	return &kvLog{
		db:            db,
		prefix:        prefix,
		nextIndex:     nextIndex,
		propose:       make(chan replication.LogEntry, 100),
		leaderHintSet: leaderHintSet,
		waitCommitted: make(chan replication.LogEntry),
		stop:          make(chan struct{}),
		stopped:       make(chan struct{}),
	}, nil
}
func (l *kvLog) Start(lo uint64) error {
	l.skipBefore = lo
	go l.run()
	return nil
}
func (l *kvLog) Stop() error {
	l.stopOnce.Do(func() {
		close(l.stop)
		<-l.stopped
	})
	return nil
}
func (l *kvLog) ApplyConfChange(*replication.ConfChange) {
	panic("ApplyConfChange: cannot reconfigure kvlog")
}
func (l *kvLog) Propose(ctx context.Context, en replication.LogEntry) {
	if en.ConfChange != nil && en.ConfChange.Operation != replication.ConfChangeNOP {
		panic("Propose: cannot reconfigure kvlog")
	}
	select {
	case l.propose <- replication.LogEntry{Data: en.Data}:
	case <-l.stop:
	}
}
func (l *kvLog) WaitCommitted() <-chan replication.LogEntry {
	return l.waitCommitted
}
func (l *kvLog) LeaderHintSet() <-chan bool {
	return l.leaderHintSet
}
func (l *kvLog) GetCommitted(lo, hi, maxSize uint64) (ret []replication.LogEntry, err error) {
	size := uint64(0)
	for i := lo; i < hi; i++ {
		var v replication.LogEntry
		v, err = l.get(i)
		if err != nil {
			if err == l.db.ErrNotFound() {
				return ret, nil
			}
			return nil, err
		}
		if len(ret) != 0 && size+uint64(len(v.Data)) > maxSize {
			return
		}
		ret = append(ret, v)
		size += uint64(len(v.Data))
		if size >= maxSize {
			return
		}
	}
	return
}