@@ -11,6 +11,7 @@ import (
1111 "encoding/binary"
1212 "fmt"
1313 "io"
14+ "maps"
1415 "slices"
1516 "strings"
1617 "time"
@@ -162,7 +163,10 @@ type VersionEdit struct {
162163 // DeletedBlobFiles holds all blob files that became unreferenced during the
163164 // version edit. These blob files must not be referenced by any sstable in
164165 // the resulting Version.
165- DeletedBlobFiles []base.DiskFileNum
166+ //
167+ // While replaying a MANIFEST, the values are nil. Otherwise the values must
168+ // not be nil.
169+ DeletedBlobFiles map [base.DiskFileNum ]* BlobFileMetadata
166170}
167171
168172// Decode decodes an edit from the specified reader.
@@ -536,7 +540,10 @@ func (v *VersionEdit) Decode(r io.Reader) error {
536540 if err != nil {
537541 return err
538542 }
539- v .DeletedBlobFiles = append (v .DeletedBlobFiles , base .DiskFileNum (fileNum ))
543+ if v .DeletedBlobFiles == nil {
544+ v .DeletedBlobFiles = make (map [base.DiskFileNum ]* BlobFileMetadata )
545+ }
546+ v .DeletedBlobFiles [base .DiskFileNum (fileNum )] = nil
540547
541548 case tagPrevLogNumber :
542549 n , err := d .readUvarint ()
@@ -572,10 +579,7 @@ func (v *VersionEdit) string(verbose bool, fmtKey base.FormatKey) string {
572579 if v .LastSeqNum != 0 {
573580 fmt .Fprintf (& buf , " last-seq-num: %d\n " , v .LastSeqNum )
574581 }
575- entries := make ([]DeletedTableEntry , 0 , len (v .DeletedTables ))
576- for df := range v .DeletedTables {
577- entries = append (entries , df )
578- }
582+ entries := slices .Collect (maps .Keys (v .DeletedTables ))
579583 slices .SortFunc (entries , func (a , b DeletedTableEntry ) int {
580584 if v := stdcmp .Compare (a .Level , b .Level ); v != 0 {
581585 return v
@@ -604,7 +608,9 @@ func (v *VersionEdit) string(verbose bool, fmtKey base.FormatKey) string {
604608 for _ , f := range v .NewBlobFiles {
605609 fmt .Fprintf (& buf , " add-blob-file: %s\n " , f .String ())
606610 }
607- for _ , df := range v .DeletedBlobFiles {
611+ deletedBlobFiles := slices .Collect (maps .Keys (v .DeletedBlobFiles ))
612+ slices .Sort (deletedBlobFiles )
613+ for _ , df := range deletedBlobFiles {
608614 fmt .Fprintf (& buf , " del-blob-file: %s\n " , df )
609615 }
610616 return buf .String ()
@@ -686,7 +692,10 @@ func ParseVersionEditDebug(s string) (_ *VersionEdit, err error) {
686692 ve .NewBlobFiles = append (ve .NewBlobFiles , meta )
687693
688694 case "del-blob-file" :
689- ve .DeletedBlobFiles = append (ve .DeletedBlobFiles , p .DiskFileNum ())
695+ if ve .DeletedBlobFiles == nil {
696+ ve .DeletedBlobFiles = make (map [base.DiskFileNum ]* BlobFileMetadata )
697+ }
698+ ve .DeletedBlobFiles [p .DiskFileNum ()] = nil
690699
691700 default :
692701 return nil , errors .Errorf ("field %q not implemented" , field )
@@ -821,7 +830,7 @@ func (v *VersionEdit) Encode(w io.Writer) error {
821830 e .writeUvarint (x .ValueSize )
822831 e .writeUvarint (x .CreationTime )
823832 }
824- for _ , x := range v .DeletedBlobFiles {
833+ for x := range v .DeletedBlobFiles {
825834 e .writeUvarint (tagDeletedBlobFile )
826835 e .writeUvarint (uint64 (x ))
827836 }
@@ -937,7 +946,7 @@ type BulkVersionEdit struct {
937946 // any sstables, making them obsolete within the resulting version (a
938947 // zombie if still referenced by previous versions). Deleted file
939948 // numbers must not exist in Added.
940- Deleted [] base.DiskFileNum
949+ Deleted map [ base.DiskFileNum ] * BlobFileMetadata
941950 // DeletedReferences holds metadata of blob files referenced by tables
942951 // deleted in the accumulated version edits. This is used during replay
943952 // to populate the *BlobFileMetadata pointers of new blob references,
@@ -1015,8 +1024,8 @@ func (b *BulkVersionEdit) Accumulate(ve *VersionEdit) error {
10151024 b .BlobFiles .Added [nbf .FileNum ] = nbf
10161025 }
10171026
1018- b .BlobFiles .Deleted = slices . Grow ( b . BlobFiles . Deleted , len (ve .DeletedBlobFiles ))
1019- for _ , dbf := range ve .DeletedBlobFiles {
1027+ b .BlobFiles .Deleted = make ( map [base. DiskFileNum ] * BlobFileMetadata , len (ve .DeletedBlobFiles ))
1028+ for dbf , blobMeta := range ve .DeletedBlobFiles {
10201029 // If the blob file was added in a prior, accumulated version edit we
10211030 // can resolve the deletion by removing it from the added files map.
10221031 // Otherwise the blob file deleted was added prior to this bulk edit,
@@ -1025,7 +1034,7 @@ func (b *BulkVersionEdit) Accumulate(ve *VersionEdit) error {
10251034 if b .BlobFiles .Added != nil && b .BlobFiles .Added [dbf ] != nil {
10261035 delete (b .BlobFiles .Added , dbf )
10271036 } else {
1028- b .BlobFiles .Deleted = append ( b . BlobFiles . Deleted , dbf )
1037+ b .BlobFiles .Deleted [ dbf ] = blobMeta
10291038 }
10301039 }
10311040
@@ -1307,7 +1316,10 @@ func (b *BulkVersionEdit) Apply(curr *Version, readCompactionRate int64) (*Versi
13071316 for _ , deletedLevel := range b .DeletedTables {
13081317 for _ , dt := range deletedLevel {
13091318 for _ , ref := range dt .BlobReferences {
1310- if ref .Metadata .ActiveRefs .count == 0 && ! slices .Contains (b .BlobFiles .Deleted , ref .FileNum ) {
1319+ if ref .Metadata .ActiveRefs .count != 0 {
1320+ continue
1321+ }
1322+ if _ , ok := b .BlobFiles .Deleted [ref .FileNum ]; ! ok {
13111323 panic (errors .AssertionFailedf ("blob file %s has no active refs, but was not deleted in the version edit" , ref .FileNum ))
13121324 }
13131325 }
0 commit comments