@@ -280,14 +280,20 @@ func (d *DB) runBlobFileRewriteLocked(
280
280
Path : d .objProvider .Path (objMeta ),
281
281
FileNum : objMeta .DiskFileNum ,
282
282
})
283
- // Initialize a blob file writer . We pass L6 to MakeBlobWriterOptions.
283
+ // Initialize a blob file rewriter . We pass L6 to MakeBlobWriterOptions.
284
284
// There's no single associated level with a blob file. A long-lived blob
285
285
// file that gets rewritten is likely to mostly be referenced from L6.
286
286
// TODO(jackson): Consider refactoring to remove the level association.
287
- writer := blob .NewFileWriter (newDiskFileNum , writable , d .opts .MakeBlobWriterOptions (6 ))
288
-
287
+ rewriter := newBlobFileRewriter (
288
+ d .fileCache ,
289
+ env ,
290
+ newDiskFileNum ,
291
+ writable ,
292
+ d .opts .MakeBlobWriterOptions (6 ),
293
+ c .referencingTables ,
294
+ c .input ,
295
+ )
289
296
// Perform the rewrite.
290
- rewriter := newBlobFileRewriter (d .fileCache , env , writer , c .referencingTables , c .input )
291
297
stats , err := rewriter .Rewrite (ctx )
292
298
if err != nil {
293
299
return objstorage.ObjectMetadata {}, nil , err
@@ -361,51 +367,35 @@ type blockValues struct {
361
367
liveValueIDs []int
362
368
}
363
369
364
- // blobFileMapping implements blob.FileMapping to always map to the input blob
365
- // file.
366
- type blobFileMapping struct {
367
- fileNum base.DiskFileNum
368
- }
369
-
370
- // Assert that (*blobFileMapping) implements blob.FileMapping.
371
- var _ blob.FileMapping = (* blobFileMapping )(nil )
372
-
373
- func (m * blobFileMapping ) Lookup (fileID base.BlobFileID ) (base.DiskFileNum , bool ) {
374
- return m .fileNum , true
375
- }
376
-
377
370
// blobFileRewriter is responsible for rewriting blob files by combining and
378
371
// processing blob reference liveness encodings from multiple SSTables. It
379
372
// maintains state for writing to an output blob file.
380
373
type blobFileRewriter struct {
381
- fc * fileCacheHandle
382
- env block.ReadEnv
383
- sstables []* manifest.TableMetadata
384
-
385
- inputBlob manifest.BlobFileMetadata
386
- valueFetcher blob.ValueFetcher
387
- fileMapping blobFileMapping
388
- blkHeap blockHeap
389
-
390
- // Current blob writer state.
391
- writer * blob.FileWriter
374
+ fc * fileCacheHandle
375
+ readEnv block.ReadEnv
376
+ sstables []* manifest.TableMetadata
377
+ inputBlob manifest.BlobFileMetadata
378
+ rw * blob.FileRewriter
379
+ blkHeap blockHeap
392
380
}
393
381
394
382
func newBlobFileRewriter (
395
383
fc * fileCacheHandle ,
396
- env block.ReadEnv ,
397
- writer * blob.FileWriter ,
384
+ readEnv block.ReadEnv ,
385
+ outputFileNum base.DiskFileNum ,
386
+ w objstorage.Writable ,
387
+ opts blob.FileWriterOptions ,
398
388
sstables []* manifest.TableMetadata ,
399
389
inputBlob manifest.BlobFileMetadata ,
400
390
) * blobFileRewriter {
391
+ rw := blob .NewFileRewriter (inputBlob .FileID , inputBlob .Physical .FileNum , fc , readEnv , outputFileNum , w , opts )
401
392
return & blobFileRewriter {
402
- fc : fc ,
403
- env : env ,
404
- writer : writer ,
405
- sstables : sstables ,
406
- inputBlob : inputBlob ,
407
- fileMapping : blobFileMapping {fileNum : inputBlob .Physical .FileNum },
408
- blkHeap : blockHeap {},
393
+ fc : fc ,
394
+ readEnv : readEnv ,
395
+ rw : rw ,
396
+ sstables : sstables ,
397
+ inputBlob : inputBlob ,
398
+ blkHeap : blockHeap {},
409
399
}
410
400
}
411
401
@@ -426,7 +416,7 @@ func (rw *blobFileRewriter) generateHeap() error {
426
416
return errors .AssertionFailedf ("table %s doesn't contain a reference to blob file %s" ,
427
417
sst .TableNum , rw .inputBlob .FileID )
428
418
}
429
- err := rw .fc .withReader (ctx , rw .env , sst , func (r * sstable.Reader , readEnv sstable.ReadEnv ) error {
419
+ err := rw .fc .withReader (ctx , rw .readEnv , sst , func (r * sstable.Reader , readEnv sstable.ReadEnv ) error {
430
420
h , err := r .ReadBlobRefIndexBlock (ctx , readEnv .Block )
431
421
if err != nil {
432
422
return err
@@ -449,42 +439,8 @@ func (rw *blobFileRewriter) generateHeap() error {
449
439
return nil
450
440
}
451
441
452
- // copyBlockValues copies the live values from the given block to the output
453
- // blob file, flushing the current block before if necessary.
454
- func (rw * blobFileRewriter ) copyBlockValues (ctx context.Context , finishedBlock blockValues ) error {
455
- shouldFlush := rw .writer .ShouldFlushBefore (finishedBlock .valuesSize )
456
- if shouldFlush {
457
- rw .writer .ForceFlush ()
458
- }
459
-
460
- // Record the mapping from the virtual block ID to the current physical
461
- // block and value ID offset.
462
- rw .writer .BeginNewVirtualBlock (finishedBlock .blockID )
463
- slices .Sort (finishedBlock .liveValueIDs )
464
-
465
- for i , valueID := range finishedBlock .liveValueIDs {
466
- if i > 0 && finishedBlock .liveValueIDs [i - 1 ]+ 1 != valueID {
467
- // There's a gap in the referenced value IDs.
468
- for missing := finishedBlock .liveValueIDs [i - 1 ] + 1 ; missing < valueID ; missing ++ {
469
- rw .writer .AddValue (nil )
470
- }
471
- }
472
-
473
- value , _ , err := rw .valueFetcher .Fetch (ctx , rw .inputBlob .FileID , finishedBlock .blockID , blob .BlockValueID (valueID ))
474
- if err != nil {
475
- return err
476
- }
477
- rw .writer .AddValue (value )
478
- }
479
- return nil
480
- }
481
-
482
442
func (rw * blobFileRewriter ) Rewrite (ctx context.Context ) (blob.FileWriterStats , error ) {
483
- rw .valueFetcher .Init (& rw .fileMapping , rw .fc , rw .env )
484
- defer func () { _ = rw .valueFetcher .Close () }()
485
-
486
- err := rw .generateHeap ()
487
- if err != nil {
443
+ if err := rw .generateHeap (); err != nil {
488
444
return blob.FileWriterStats {}, err
489
445
}
490
446
if rw .blkHeap .Len () == 0 {
@@ -494,7 +450,7 @@ func (rw *blobFileRewriter) Rewrite(ctx context.Context) (blob.FileWriterStats,
494
450
// Begin constructing our output blob file. We maintain a map of blockID
495
451
// to accumulated liveness data across all referencing sstables.
496
452
firstBlock := heap .Pop (& rw .blkHeap ).(* sstable.BlobRefLivenessEncoding )
497
- pendingBlock := blockValues {
453
+ pending := blockValues {
498
454
blockID : firstBlock .BlockID ,
499
455
valuesSize : firstBlock .ValuesSize ,
500
456
liveValueIDs : slices .Collect (sstable .IterSetBitsInRunLengthBitmap (firstBlock .Bitmap )),
@@ -504,21 +460,23 @@ func (rw *blobFileRewriter) Rewrite(ctx context.Context) (blob.FileWriterStats,
504
460
505
461
// If we are encountering a new block, write the last accumulated block
506
462
// to the blob file.
507
- if pendingBlock .blockID != nextBlock .BlockID {
463
+ if pending .blockID != nextBlock .BlockID {
508
464
// Write the last accumulated block's values to the blob file.
509
- if err := rw .copyBlockValues (ctx , pendingBlock ); err != nil {
465
+ err := rw .rw .CopyBlock (ctx , pending .blockID , pending .valuesSize , pending .liveValueIDs )
466
+ if err != nil {
510
467
return blob.FileWriterStats {}, err
511
468
}
512
469
}
513
470
// Update the accumulated encoding for this block.
514
- pendingBlock .valuesSize += nextBlock .ValuesSize
515
- pendingBlock .liveValueIDs = slices .AppendSeq (pendingBlock .liveValueIDs ,
471
+ pending .valuesSize += nextBlock .ValuesSize
472
+ pending .liveValueIDs = slices .AppendSeq (pending .liveValueIDs ,
516
473
sstable .IterSetBitsInRunLengthBitmap (nextBlock .Bitmap ))
517
474
}
518
475
519
476
// Copy the last accumulated block.
520
- if err := rw .copyBlockValues (ctx , pendingBlock ); err != nil {
477
+ err := rw .rw .CopyBlock (ctx , pending .blockID , pending .valuesSize , pending .liveValueIDs )
478
+ if err != nil {
521
479
return blob.FileWriterStats {}, err
522
480
}
523
- return rw .writer .Close ()
481
+ return rw .rw .Close ()
524
482
}
0 commit comments