2021-11-19 05:03:36 +00:00
|
|
|
package kv
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/ledgerwatch/erigon-lib/common"
|
|
|
|
)
|
|
|
|
|
2022-01-17 09:49:02 +00:00
|
|
|
// BigChunks - read `table` by big chunks - restart read transaction after each 1 minutes
|
2021-11-19 05:03:36 +00:00
|
|
|
func BigChunks(db RoDB, table string, from []byte, walker func(tx Tx, k, v []byte) (bool, error)) error {
|
2022-01-17 09:49:02 +00:00
|
|
|
rollbackEvery := time.NewTicker(1 * time.Minute)
|
2021-11-19 05:03:36 +00:00
|
|
|
|
|
|
|
var stop bool
|
|
|
|
for !stop {
|
|
|
|
if err := db.View(context.Background(), func(tx Tx) error {
|
|
|
|
c, err := tx.Cursor(table)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
defer c.Close()
|
|
|
|
|
|
|
|
k, v, err := c.Seek(from)
|
|
|
|
Loop:
|
|
|
|
for ; k != nil; k, v, err = c.Next() {
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2022-01-17 09:49:02 +00:00
|
|
|
// break loop before walker() call, to make sure all keys are received by walker() exactly once
|
|
|
|
select {
|
|
|
|
case <-rollbackEvery.C:
|
|
|
|
|
|
|
|
break Loop
|
|
|
|
default:
|
|
|
|
}
|
|
|
|
|
2021-11-19 05:03:36 +00:00
|
|
|
ok, err := walker(tx, k, v)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if !ok {
|
|
|
|
stop = true
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-12 03:46:26 +00:00
|
|
|
if k == nil {
|
|
|
|
stop = true
|
|
|
|
}
|
|
|
|
|
2021-11-19 05:03:36 +00:00
|
|
|
from = common.Copy(k) // next transaction will start from this key
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|