@@ -234,104 +234,6 @@ func (h *History) buildVi(ctx context.Context, item *FilesItem, ps *background.P
234234}
235235
236236func (h * History ) buildVI (ctx context.Context , historyIdxPath string , hist , efHist * seg.Decompressor , efBaseTxNum uint64 , ps * background.ProgressSet ) error {
237- // file not the config is the source of truth for the .v file compression state
238- compressedPageValuesCount := hist .CompressedPageValuesCount ()
239- if hist .CompressionFormatVersion () == seg .FileCompressionFormatV0 {
240- compressedPageValuesCount = h .HistoryValuesOnCompressedPage
241- }
242-
243- if compressedPageValuesCount > 1 {
244- return h .buildVIFromPages (ctx , historyIdxPath , hist , ps )
245- }
246- return h .buildVIFromEF (ctx , historyIdxPath , hist , efHist , efBaseTxNum , ps )
247- }
248-
249- // buildVIFromPages builds the .vi index by reading keys directly from the .v file's pages.
250- // This is used for V1 files with page-level compression where each page contains multiple
251- // key-value pairs. Reading keys from the pages ensures the index correctly maps each key
252- // to its containing page, regardless of whether the .ef file has the same entry ordering.
253- func (h * History ) buildVIFromPages (ctx context.Context , historyIdxPath string , hist * seg.Decompressor , ps * background.ProgressSet ) error {
254- defer hist .MadvSequential ().DisableReadAhead ()
255-
256- histReader := h .dataReader (hist )
257-
258- // Count total entries by scanning all pages
259- cnt := 0
260- page := & seg.Page {}
261- histReader .Reset (0 )
262- for histReader .HasNext () { //TODO: use vFile.Count()
263- pageData , _ := histReader .Next (nil )
264- page .Reset (pageData , true )
265- for page .HasNext () {
266- page .Next ()
267- cnt ++
268- }
269- select {
270- case <- ctx .Done ():
271- return ctx .Err ()
272- default :
273- }
274- }
275-
276- _ , fName := filepath .Split (historyIdxPath )
277- p := ps .AddNew (fName , uint64 (cnt ))
278- defer ps .Delete (p )
279- rs , err := recsplit .NewRecSplit (recsplit.RecSplitArgs {
280- KeyCount : cnt ,
281- Enums : false ,
282- BucketSize : recsplit .DefaultBucketSize ,
283- LeafSize : recsplit .DefaultLeafSize ,
284- TmpDir : h .dirs .Tmp ,
285- IndexFile : historyIdxPath ,
286- Salt : h .salt .Load (),
287- NoFsync : h .noFsync ,
288- }, h .logger )
289- if err != nil {
290- return fmt .Errorf ("create recsplit: %w" , err )
291- }
292- defer rs .Close ()
293- rs .LogLvl (log .LvlTrace )
294-
295- for {
296- histReader .Reset (0 )
297- var valOffset uint64
298-
299- for histReader .HasNext () {
300- pageData , nextOffset := histReader .Next (nil )
301- page .Reset (pageData , true )
302- for page .HasNext () {
303- k , _ := page .Next ()
304- if err = rs .AddKey (k , valOffset ); err != nil {
305- return err
306- }
307- }
308- p .Processed .Add (1 )
309- valOffset = nextOffset
310-
311- select {
312- case <- ctx .Done ():
313- return ctx .Err ()
314- default :
315- }
316- }
317-
318- if err = rs .Build (ctx ); err != nil {
319- if rs .Collision () {
320- log .Info ("Building recsplit. Collision happened. It's ok. Restarting..." )
321- rs .ResetNextSalt ()
322- } else {
323- return fmt .Errorf ("build idx: %w" , err )
324- }
325- } else {
326- break
327- }
328- }
329- return nil
330- }
331-
332- // buildVIFromEF builds the .vi index using the .ef inverted index file to enumerate keys.
333- // This is used for V0 files or files without page-level compression.
334- func (h * History ) buildVIFromEF (ctx context.Context , historyIdxPath string , hist , efHist * seg.Decompressor , efBaseTxNum uint64 , ps * background.ProgressSet ) error {
335237 var histKey []byte
336238 var valOffset uint64
337239
@@ -342,8 +244,8 @@ func (h *History) buildVIFromEF(ctx context.Context, historyIdxPath string, hist
342244
343245 var keyBuf , valBuf []byte
344246 cnt := uint64 (0 )
345- for iiReader .HasNext () { //TODO: use vFile.Count()
346- keyBuf , _ = iiReader .Next (keyBuf [:0 ])
247+ for iiReader .HasNext () {
248+ keyBuf , _ = iiReader .Next (keyBuf [:0 ]) // skip key
347249 valBuf , _ = iiReader .Next (valBuf [:0 ])
348250 cnt += multiencseq .Count (efBaseTxNum , valBuf )
349251 select {
@@ -377,6 +279,7 @@ func (h *History) buildVIFromEF(ctx context.Context, historyIdxPath string, hist
377279 seq := & multiencseq.SequenceReader {}
378280 it := & multiencseq.SequenceIterator {}
379281
282+ i := 0
380283 for {
381284 histReader .Reset (0 )
382285 iiReader .Reset (0 )
@@ -387,6 +290,8 @@ func (h *History) buildVIFromEF(ctx context.Context, historyIdxPath string, hist
387290 valBuf , _ = iiReader .Next (valBuf [:0 ])
388291 p .Processed .Add (1 )
389292
293+ // fmt.Printf("ef key %x\n", keyBuf)
294+
390295 seq .Reset (efBaseTxNum , valBuf )
391296 it .Reset (seq , 0 )
392297 for it .HasNext () {
@@ -398,7 +303,22 @@ func (h *History) buildVIFromEF(ctx context.Context, historyIdxPath string, hist
398303 if err = rs .AddKey (histKey , valOffset ); err != nil {
399304 return err
400305 }
401- valOffset , _ = histReader .Skip ()
306+
307+ // file not the config is the source of truth for the .v file compression state
308+ compressedPageValuesCount := hist .CompressedPageValuesCount ()
309+
310+ if hist .CompressionFormatVersion () == seg .FileCompressionFormatV0 {
311+ compressedPageValuesCount = h .HistoryValuesOnCompressedPage
312+ }
313+
314+ if compressedPageValuesCount == 0 {
315+ valOffset , _ = histReader .Skip ()
316+ } else {
317+ i ++
318+ if i % compressedPageValuesCount == 0 {
319+ valOffset , _ = histReader .Skip ()
320+ }
321+ }
402322 }
403323
404324 select {
@@ -1335,6 +1255,7 @@ func (ht *HistoryRoTx) historySeekInFiles(key []byte, txNum uint64) ([]byte, boo
13351255 }
13361256 g := ht .statelessGetter (historyItem .i )
13371257 g .Reset (offset )
1258+ //fmt.Printf("[dbg] hist.seek: offset=%d\n", offset)
13381259 v , _ := g .Next (nil )
13391260 if traceGetAsOf == ht .h .FilenameBase {
13401261 fmt .Printf ("DomainGetAsOf(%s, %x, %d) -> %s, histTxNum=%d, isNil(v)=%t\n " , ht .h .FilenameBase , key , txNum , g .FileName (), histTxNum , v == nil )
@@ -1347,13 +1268,7 @@ func (ht *HistoryRoTx) historySeekInFiles(key []byte, txNum uint64) ([]byte, boo
13471268 }
13481269
13491270 if compressedPageValuesCount > 1 {
1350- v , ok , ht .snappyReadBuffer = seg .GetFromPage (historyKey , v , ht .snappyReadBuffer , true )
1351- if ! ok {
1352- // Key not found in page. The inverted index (.ef) contains a txNum
1353- // entry that has no corresponding entry in the history values (.v)
1354- // file. Fall back to DB/latest lookup to get the correct value.
1355- return nil , false , nil
1356- }
1271+ v , ht .snappyReadBuffer = seg .GetFromPage (historyKey , v , ht .snappyReadBuffer , true )
13571272 }
13581273 return v , true , nil
13591274}
@@ -1655,10 +1570,7 @@ func (ht *HistoryRoTx) HistoryDump(fromTxNum, toTxNum int, keyToDump *[]byte, du
16551570
16561571 if compressedPageValuesCount > 0 {
16571572 histKeyBuf = historyKey (txNum , key , histKeyBuf )
1658- val , ok , _ = seg .GetFromPage (histKeyBuf , val , nil , true )
1659- if ! ok {
1660- return fmt .Errorf ("HistoryDump: not found key [%x] on compressed page: %s" , key , viFile .Fullpath ())
1661- }
1573+ val , _ = seg .GetFromPage (histKeyBuf , val , nil , true )
16621574 }
16631575
16641576 dumpTo (key , txNum , val )
0 commit comments