mirror of
https://gitlab.com/pulsechaincom/erigon-pulse.git
synced 2025-01-19 00:54:12 +00:00
erigon22: historyReader22 and more tests #623
This commit is contained in:
parent
e572bef176
commit
775ace2e37
167
state/history.go
167
state/history.go
@ -628,46 +628,6 @@ func (h *History) MakeContext() *HistoryContext {
|
|||||||
}
|
}
|
||||||
func (hc *HistoryContext) SetTx(tx kv.Tx) { hc.tx = tx }
|
func (hc *HistoryContext) SetTx(tx kv.Tx) { hc.tx = tx }
|
||||||
|
|
||||||
func (hc *HistoryContext) getNoStateFromDB(key []byte, txNum uint64, tx kv.Tx) ([]byte, bool, error) {
|
|
||||||
var txKey [8]byte
|
|
||||||
binary.BigEndian.PutUint64(txKey[:], txNum)
|
|
||||||
historyKeysCursor, err := tx.CursorDupSort(hc.h.indexKeysTable)
|
|
||||||
if err != nil {
|
|
||||||
return nil, false, fmt.Errorf("create %s history cursor: %w", hc.h.filenameBase, err)
|
|
||||||
}
|
|
||||||
defer historyKeysCursor.Close()
|
|
||||||
valsC, err := tx.Cursor(hc.h.historyValsTable)
|
|
||||||
if err != nil {
|
|
||||||
return nil, false, err
|
|
||||||
}
|
|
||||||
defer valsC.Close()
|
|
||||||
v, err := historyKeysCursor.SeekBothRange(txKey[:], key)
|
|
||||||
if err != nil {
|
|
||||||
return nil, false, err
|
|
||||||
}
|
|
||||||
if len(v) > 0 {
|
|
||||||
key2, txnNumBytes := v[:len(v)-8], v[len(v)-8:]
|
|
||||||
_ = key2
|
|
||||||
_, vv, err := valsC.SeekExact(txnNumBytes)
|
|
||||||
if err != nil {
|
|
||||||
return nil, false, err
|
|
||||||
}
|
|
||||||
return vv, vv != nil, nil
|
|
||||||
}
|
|
||||||
return nil, false, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (hc *HistoryContext) GetNoStateWithRecent(key []byte, txNum uint64, tx kv.Tx) ([]byte, bool, error) {
|
|
||||||
enc, ok, err := hc.getNoStateFromDB(key, txNum, tx)
|
|
||||||
if err != nil {
|
|
||||||
return nil, false, err
|
|
||||||
}
|
|
||||||
if ok {
|
|
||||||
return enc, true, nil
|
|
||||||
}
|
|
||||||
return hc.GetNoState(key, txNum)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (hc *HistoryContext) GetNoState(key []byte, txNum uint64) ([]byte, bool, error) {
|
func (hc *HistoryContext) GetNoState(key []byte, txNum uint64) ([]byte, bool, error) {
|
||||||
//fmt.Printf("GetNoState [%x] %d\n", key, txNum)
|
//fmt.Printf("GetNoState [%x] %d\n", key, txNum)
|
||||||
var foundTxNum uint64
|
var foundTxNum uint64
|
||||||
@ -722,3 +682,130 @@ func (hc *HistoryContext) GetNoState(key []byte, txNum uint64) ([]byte, bool, er
|
|||||||
}
|
}
|
||||||
return nil, false, nil
|
return nil, false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetNoStateWithRecent searches history for a value of specified key before txNum
|
||||||
|
// second return value is true if the value is found in the history (even if it is nil)
|
||||||
|
func (hc *HistoryContext) GetNoStateWithRecent(key []byte, txNum uint64, roTx kv.Tx) ([]byte, bool, error) {
|
||||||
|
var search ctxItem
|
||||||
|
search.startTxNum = txNum
|
||||||
|
search.endTxNum = txNum
|
||||||
|
var foundTxNum uint64
|
||||||
|
var foundEndTxNum uint64
|
||||||
|
var foundStartTxNum uint64
|
||||||
|
var found bool
|
||||||
|
var anyItem bool // Whether any filesItem has been looked at in the loop below
|
||||||
|
var topState *ctxItem
|
||||||
|
hc.historyFiles.AscendGreaterOrEqual(&search, func(i *ctxItem) bool {
|
||||||
|
topState = i
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
hc.indexFiles.AscendGreaterOrEqual(&search, func(item *ctxItem) bool {
|
||||||
|
anyItem = true
|
||||||
|
offset := item.reader.Lookup(key)
|
||||||
|
g := item.getter
|
||||||
|
g.Reset(offset)
|
||||||
|
if k, _ := g.NextUncompressed(); bytes.Equal(k, key) {
|
||||||
|
eliasVal, _ := g.NextUncompressed()
|
||||||
|
ef, _ := eliasfano32.ReadEliasFano(eliasVal)
|
||||||
|
//start := time.Now()
|
||||||
|
n, ok := ef.Search(txNum)
|
||||||
|
//d.stats.EfSearchTime += time.Since(start)
|
||||||
|
if ok {
|
||||||
|
foundTxNum = n
|
||||||
|
foundEndTxNum = item.endTxNum
|
||||||
|
foundStartTxNum = item.startTxNum
|
||||||
|
found = true
|
||||||
|
return false
|
||||||
|
} else if item.endTxNum > txNum && item.endTxNum >= topState.endTxNum {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
if found {
|
||||||
|
var txKey [8]byte
|
||||||
|
binary.BigEndian.PutUint64(txKey[:], foundTxNum)
|
||||||
|
var historyItem *ctxItem
|
||||||
|
search.startTxNum = foundStartTxNum
|
||||||
|
search.endTxNum = foundEndTxNum
|
||||||
|
historyItem, ok := hc.historyFiles.Get(&search)
|
||||||
|
if !ok || historyItem == nil {
|
||||||
|
return nil, false, fmt.Errorf("no %s file found for [%x]", hc.h.filenameBase, key)
|
||||||
|
}
|
||||||
|
offset := historyItem.reader.Lookup2(txKey[:], key)
|
||||||
|
g := historyItem.getter
|
||||||
|
g.Reset(offset)
|
||||||
|
if hc.h.compressVals {
|
||||||
|
v, _ := g.Next(nil)
|
||||||
|
return v, true, nil
|
||||||
|
}
|
||||||
|
v, _ := g.NextUncompressed()
|
||||||
|
return v, true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if anyItem {
|
||||||
|
// If there were no changes but there were history files, the value can be obtained from value files
|
||||||
|
var val []byte
|
||||||
|
hc.historyFiles.DescendLessOrEqual(topState, func(item *ctxItem) bool {
|
||||||
|
if item.reader.Empty() {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
offset := item.reader.Lookup(key)
|
||||||
|
g := item.getter
|
||||||
|
g.Reset(offset)
|
||||||
|
if g.HasNext() {
|
||||||
|
if k, _ := g.NextUncompressed(); bytes.Equal(k, key) {
|
||||||
|
if hc.h.compressVals {
|
||||||
|
val, _ = g.Next(nil)
|
||||||
|
} else {
|
||||||
|
val, _ = g.NextUncompressed()
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
return val, true, nil
|
||||||
|
}
|
||||||
|
// Value not found in history files, look in the recent history
|
||||||
|
if roTx == nil {
|
||||||
|
return nil, false, fmt.Errorf("roTx is nil")
|
||||||
|
}
|
||||||
|
return hc.getNoStateFromDB(key, txNum, roTx)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hc *HistoryContext) getNoStateFromDB(key []byte, txNum uint64, tx kv.Tx) ([]byte, bool, error) {
|
||||||
|
indexCursor, err := tx.CursorDupSort(hc.h.indexTable)
|
||||||
|
if err != nil {
|
||||||
|
return nil, false, err
|
||||||
|
}
|
||||||
|
defer indexCursor.Close()
|
||||||
|
var txKey [8]byte
|
||||||
|
binary.BigEndian.PutUint64(txKey[:], txNum)
|
||||||
|
var foundTxNumVal []byte
|
||||||
|
if foundTxNumVal, err = indexCursor.SeekBothRange(key, txKey[:]); err != nil {
|
||||||
|
return nil, false, err
|
||||||
|
}
|
||||||
|
if foundTxNumVal != nil {
|
||||||
|
var historyKeysCursor kv.CursorDupSort
|
||||||
|
if historyKeysCursor, err = tx.CursorDupSort(hc.h.indexKeysTable); err != nil {
|
||||||
|
return nil, false, err
|
||||||
|
}
|
||||||
|
defer historyKeysCursor.Close()
|
||||||
|
var vn []byte
|
||||||
|
if vn, err = historyKeysCursor.SeekBothRange(foundTxNumVal, key); err != nil {
|
||||||
|
return nil, false, err
|
||||||
|
}
|
||||||
|
valNum := binary.BigEndian.Uint64(vn[len(vn)-8:])
|
||||||
|
if valNum == 0 {
|
||||||
|
// This is special valNum == 0, which is empty value
|
||||||
|
return nil, true, nil
|
||||||
|
}
|
||||||
|
var v []byte
|
||||||
|
if v, err = tx.GetOne(hc.h.historyValsTable, vn[len(vn)-8:]); err != nil {
|
||||||
|
return nil, false, err
|
||||||
|
}
|
||||||
|
return v, true, nil
|
||||||
|
}
|
||||||
|
return nil, false, nil
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user