@@ -81,6 +81,13 @@ type DeletedTableEntry struct {
81
81
FileNum base.FileNum
82
82
}
83
83
84
+ // DeletedBlobFileEntry holds the state for a blob file deletion. The blob file
85
+ // ID may still be in-use with a different physical blob file.
86
+ type DeletedBlobFileEntry struct {
87
+ FileID base.BlobFileID
88
+ FileNum base.DiskFileNum
89
+ }
90
+
84
91
// NewTableEntry holds the state for a new sstable or one moved from a different
85
92
// level.
86
93
type NewTableEntry struct {
@@ -158,13 +165,20 @@ type VersionEdit struct {
158
165
// NewBlobFiles holds the metadata for all new blob files introduced within
159
166
// the version edit.
160
167
NewBlobFiles []BlobFileMetadata
161
- // DeletedBlobFiles holds all blob files that became unreferenced during the
162
- // version edit. These blob files must not be referenced by any sstable in
163
- // the resulting Version.
168
+ // DeletedBlobFiles holds all physical blob files that became unused during
169
+ // the version edit.
170
+ //
171
+ // A physical blob file may become unused if the corresponding BlobFileID
172
+ // becomes unreferenced during the version edit. In this case the BlobFileID
173
+ // is not referenced by any sstable in the resulting Version.
174
+ //
175
+ // A physical blob file may also become unused if it is being replaced by a
176
+ // new physical blob file. In this case NewBlobFiles must contain a
177
+ // BlobFileMetadata with the same BlobFileID.
164
178
//
165
179
// While replaying a MANIFEST, the values are nil. Otherwise the values must
166
180
// not be nil.
167
- DeletedBlobFiles map [base. BlobFileID ]* PhysicalBlobFile
181
+ DeletedBlobFiles map [DeletedBlobFileEntry ]* PhysicalBlobFile
168
182
}
169
183
170
184
// Decode decodes an edit from the specified reader.
@@ -538,14 +552,21 @@ func (v *VersionEdit) Decode(r io.Reader) error {
538
552
})
539
553
540
554
case tagDeletedBlobFile :
555
+ fileID , err := d .readUvarint ()
556
+ if err != nil {
557
+ return err
558
+ }
541
559
fileNum , err := d .readFileNum ()
542
560
if err != nil {
543
561
return err
544
562
}
545
563
if v .DeletedBlobFiles == nil {
546
- v .DeletedBlobFiles = make (map [base. BlobFileID ]* PhysicalBlobFile )
564
+ v .DeletedBlobFiles = make (map [DeletedBlobFileEntry ]* PhysicalBlobFile )
547
565
}
548
- v .DeletedBlobFiles [base .BlobFileID (fileNum )] = nil
566
+ v .DeletedBlobFiles [DeletedBlobFileEntry {
567
+ FileID : base .BlobFileID (fileID ),
568
+ FileNum : base .DiskFileNum (fileNum ),
569
+ }] = nil
549
570
550
571
case tagPrevLogNumber :
551
572
n , err := d .readUvarint ()
@@ -610,10 +631,15 @@ func (v *VersionEdit) string(verbose bool, fmtKey base.FormatKey) string {
610
631
for _ , f := range v .NewBlobFiles {
611
632
fmt .Fprintf (& buf , " add-blob-file: %s\n " , f .String ())
612
633
}
613
- deletedBlobFiles := slices .Collect (maps .Keys (v .DeletedBlobFiles ))
614
- slices .Sort (deletedBlobFiles )
615
- for _ , df := range deletedBlobFiles {
616
- fmt .Fprintf (& buf , " del-blob-file: %s\n " , df )
634
+ deletedBlobFileEntries := slices .Collect (maps .Keys (v .DeletedBlobFiles ))
635
+ slices .SortFunc (deletedBlobFileEntries , func (a , b DeletedBlobFileEntry ) int {
636
+ if v := stdcmp .Compare (a .FileID , b .FileID ); v != 0 {
637
+ return v
638
+ }
639
+ return stdcmp .Compare (a .FileNum , b .FileNum )
640
+ })
641
+ for _ , df := range deletedBlobFileEntries {
642
+ fmt .Fprintf (& buf , " del-blob-file: %s %s\n " , df .FileID , df .FileNum )
617
643
}
618
644
return buf .String ()
619
645
}
@@ -695,9 +721,12 @@ func ParseVersionEditDebug(s string) (_ *VersionEdit, err error) {
695
721
696
722
case "del-blob-file" :
697
723
if ve .DeletedBlobFiles == nil {
698
- ve .DeletedBlobFiles = make (map [base. BlobFileID ]* PhysicalBlobFile )
724
+ ve .DeletedBlobFiles = make (map [DeletedBlobFileEntry ]* PhysicalBlobFile )
699
725
}
700
- ve .DeletedBlobFiles [p .BlobFileID ()] = nil
726
+ ve .DeletedBlobFiles [DeletedBlobFileEntry {
727
+ FileID : p .BlobFileID (),
728
+ FileNum : p .DiskFileNum (),
729
+ }] = nil
701
730
702
731
default :
703
732
return nil , errors .Errorf ("field %q not implemented" , field )
@@ -837,7 +866,8 @@ func (v *VersionEdit) Encode(w io.Writer) error {
837
866
}
838
867
for x := range v .DeletedBlobFiles {
839
868
e .writeUvarint (tagDeletedBlobFile )
840
- e .writeUvarint (uint64 (x ))
869
+ e .writeUvarint (uint64 (x .FileID ))
870
+ e .writeUvarint (uint64 (x .FileNum ))
841
871
}
842
872
_ , err := w .Write (e .Bytes ())
843
873
return err
@@ -1030,20 +1060,24 @@ func (b *BulkVersionEdit) Accumulate(ve *VersionEdit) error {
1030
1060
b .BlobFiles .Added [nbf .FileID ] = nbf .Physical
1031
1061
}
1032
1062
1033
- for blobFileID , physicalBlobFile := range ve .DeletedBlobFiles {
1034
- if b .BlobFiles .Deleted == nil {
1035
- b .BlobFiles .Deleted = make (map [base.BlobFileID ]* PhysicalBlobFile )
1036
- }
1063
+ for entry , physicalBlobFile := range ve .DeletedBlobFiles {
1037
1064
// If the blob file was added in a prior, accumulated version edit we
1038
1065
// can resolve the deletion by removing it from the added files map.
1066
+ if b .BlobFiles .Added != nil {
1067
+ added := b .BlobFiles .Added [entry .FileID ]
1068
+ if added != nil && added .FileNum == entry .FileNum {
1069
+ delete (b .BlobFiles .Added , entry .FileID )
1070
+ continue
1071
+ }
1072
+ }
1039
1073
// Otherwise the blob file deleted was added prior to this bulk edit,
1040
1074
// and we insert it into BlobFiles.Deleted so that Apply may remove it
1041
1075
// from the resulting version.
1042
- if b .BlobFiles .Added != nil && b .BlobFiles .Added [blobFileID ] != nil {
1043
- delete (b .BlobFiles .Added , blobFileID )
1044
- } else {
1045
- b .BlobFiles .Deleted [blobFileID ] = physicalBlobFile
1076
+ if b .BlobFiles .Deleted == nil {
1077
+ b .BlobFiles .Deleted = make (map [base.BlobFileID ]* PhysicalBlobFile )
1046
1078
}
1079
+ b .BlobFiles .Deleted [entry .FileID ] = physicalBlobFile
1080
+
1047
1081
}
1048
1082
1049
1083
for df , m := range ve .DeletedTables {
0 commit comments