Sync using indexv2

This commit is contained in:
Martin Boehm 2018-04-30 14:50:19 +02:00
parent df2a6b5551
commit b3b8512958
2 changed files with 34 additions and 28 deletions

View File

@ -51,7 +51,7 @@ var (
prof = flag.String("prof", "", "http server binding [address]:port of the interface to profiling data /debug/pprof/ (default no profiling)") prof = flag.String("prof", "", "http server binding [address]:port of the interface to profiling data /debug/pprof/ (default no profiling)")
syncChunk = flag.Int("chunk", 100, "block chunk size for processing") syncChunk = flag.Int("chunk", 100, "block chunk size for processing")
syncWorkers = flag.Int("workers", 8, "number of workers to process blocks") syncWorkers = flag.Int("workers", 8, "number of workers to process blocks (default 8)")
dryRun = flag.Bool("dryrun", false, "do not index blocks, only download") dryRun = flag.Bool("dryrun", false, "do not index blocks, only download")
httpServerBinding = flag.String("httpserver", "", "http server binding [address]:port, (default no http server)") httpServerBinding = flag.String("httpserver", "", "http server binding [address]:port, (default no http server)")

View File

@ -187,6 +187,7 @@ func (w *SyncWorker) connectBlocks(onNewBlock func(hash string)) error {
return nil return nil
} }
// ConnectBlocksParallel uses parallel goroutines to get data from blockchain daemon
func (w *SyncWorker) ConnectBlocksParallel(lower, higher uint32) error { func (w *SyncWorker) ConnectBlocksParallel(lower, higher uint32) error {
type hashHeight struct { type hashHeight struct {
hash string hash string
@ -200,21 +201,24 @@ func (w *SyncWorker) ConnectBlocksParallel(lower, higher uint32) error {
hchClosed.Store(false) hchClosed.Store(false)
var getBlockMux sync.Mutex var getBlockMux sync.Mutex
getBlockCond := sync.NewCond(&getBlockMux) getBlockCond := sync.NewCond(&getBlockMux)
totalWaitDuration := time.Duration(0) lastConnectedBlock := lower - 1
lastConnectedBlock := int(lower) - 1
writeBlockDone := make(chan struct{}) writeBlockDone := make(chan struct{})
writeBlock := func() { writeBlockWorker := func() {
defer close(writeBlockDone) defer close(writeBlockDone)
lastBlock := lower - 1
for b := range bch { for b := range bch {
// glog.Info("WriteBlock ", b.Height) if lastBlock+1 != b.Height {
err = w.db.ConnectBlock(b) glog.Error("writeBlockWorker skipped block, last connected block", lastBlock, ", new block ", b.Height)
if err != nil {
glog.Error("WriteBlock worker ", b.Height, " ", b.Hash, " error ", err)
} }
err := w.db.ConnectBlock(b)
if err != nil {
glog.Error("writeBlockWorker ", b.Height, " ", b.Hash, " error ", err)
}
lastBlock = b.Height
} }
glog.Info("WriteBlock exiting...") glog.Info("WriteBlock exiting...")
} }
getBlock := func(i int) { getBlockWorker := func(i int) {
defer wg.Done() defer wg.Done()
var err error var err error
var block *bchain.Block var block *bchain.Block
@ -224,10 +228,10 @@ func (w *SyncWorker) ConnectBlocksParallel(lower, higher uint32) error {
if err != nil { if err != nil {
// signal came while looping in the error loop // signal came while looping in the error loop
if hchClosed.Load() == true { if hchClosed.Load() == true {
glog.Error("Worker ", i, " connect block error ", err, ". Exiting...") glog.Error("getBlockWorker ", i, " connect block error ", err, ". Exiting...")
return return
} }
glog.Error("Worker ", i, " connect block error ", err, ". Retrying...") glog.Error("getBlockWorker ", i, " connect block error ", err, ". Retrying...")
w.metrics.IndexResyncErrors.With(common.Labels{"error": err.Error()}).Inc() w.metrics.IndexResyncErrors.With(common.Labels{"error": err.Error()}).Inc()
time.Sleep(time.Millisecond * 500) time.Sleep(time.Millisecond * 500)
} else { } else {
@ -237,34 +241,32 @@ func (w *SyncWorker) ConnectBlocksParallel(lower, higher uint32) error {
if w.dryRun { if w.dryRun {
continue continue
} }
start := time.Now()
getBlockMux.Lock() getBlockMux.Lock()
for { for {
if uint32(lastConnectedBlock+1) == hh.height { // we must make sure that the blocks are written to db in the correct order
lastConnectedBlock = int(hh.height) if lastConnectedBlock+1 == hh.height {
// get data to writeBlock routine // we have the right block, pass it to the writeBlockWorker
// glog.Info("Worker ", i, " have block ", hh.height, ". Sending.") lastConnectedBlock = hh.height
bch <- block bch <- block
totalWaitDuration += time.Since(start)
getBlockCond.Broadcast() getBlockCond.Broadcast()
getBlockMux.Unlock()
break break
} }
// glog.Info("Worker ", i, " have block ", hh.height, ". Waiting.") // break the endless loop on OS signal
getBlockCond.Wait()
if hchClosed.Load() == true { if hchClosed.Load() == true {
break break
} }
// wait for the time this block is top be passed to the writeBlockWorker
getBlockCond.Wait()
} }
getBlockMux.Unlock()
} }
glog.Info("Worker ", i, " exiting...") glog.Info("getBlockWorker ", i, " exiting...")
} }
for i := 0; i < w.syncWorkers; i++ { for i := 0; i < w.syncWorkers; i++ {
wg.Add(1) wg.Add(1)
go getBlock(i) go getBlockWorker(i)
} }
go writeBlock() go writeBlockWorker()
var hash string var hash string
ConnectLoop: ConnectLoop:
for h := lower; h <= higher; { for h := lower; h <= higher; {
@ -282,16 +284,20 @@ ConnectLoop:
} }
hch <- hashHeight{hash, h} hch <- hashHeight{hash, h}
if h > 0 && h%1000 == 0 { if h > 0 && h%1000 == 0 {
glog.Info("connecting block ", h, " ", hash, " wait for writeBlock ", totalWaitDuration) glog.Info("connecting block ", h, " ", hash)
} }
h++ h++
} }
} }
close(hch) close(hch)
// signal stop to workers that are in w.chain.GetBlockWithoutHeader error loop // signal stop to workers that are in a loop
hchClosed.Store(true) hchClosed.Store(true)
// first wait for the getBlock routines to finish and then close bch channel // broadcast syncWorkers times to unstuck all waiting getBlockWorkers
getBlockCond.Broadcast() for i := 0; i < w.syncWorkers; i++ {
getBlockCond.Broadcast()
}
// first wait for the getBlockWorkers to finish and then close bch channel
// so that the getBlockWorkers do not write to the closed channel
wg.Wait() wg.Wait()
close(bch) close(bch)
<-writeBlockDone <-writeBlockDone