@@ -70,16 +70,18 @@ func (s *Store[H]) DeleteTo(ctx context.Context, to uint64) error {
70
70
return fmt .Errorf ("header/store: delete to %d below current tail(%d)" , to , tail .Height ())
71
71
}
72
72
73
- if err := s .deleteRange (ctx , tail .Height (), to ); err != nil {
74
- return fmt .Errorf ("header/store: delete to height %d: %w" , to , err )
75
- }
76
-
77
- if head .Height ()+ 1 == to {
73
+ err = s .deleteRange (ctx , tail .Height (), to )
74
+ if errors .Is (err , header .ErrNotFound ) && head .Height ()+ 1 == to {
78
75
// this is the case where we have deleted all the headers
79
76
// wipe the store
80
77
if err := s .wipe (ctx ); err != nil {
81
78
return fmt .Errorf ("header/store: wipe: %w" , err )
82
79
}
80
+
81
+ return nil
82
+ }
83
+ if err != nil {
84
+ return fmt .Errorf ("header/store: delete to height %d: %w" , to , err )
83
85
}
84
86
85
87
return nil
@@ -117,28 +119,29 @@ func (s *Store[H]) deleteRange(ctx context.Context, from, to uint64) (err error)
117
119
)
118
120
}
119
121
} else if to - from > 1 {
120
- log .Debugw ("deleted headers" , "from_height" , from , "to_height" , to , "took" , time .Since (startTime ))
122
+ log .Debugw ("deleted headers" , "from_height" , from , "to_height" , to , "took(s) " , time .Since (startTime ). Seconds ( ))
121
123
}
122
124
123
125
if derr := s .setTail (ctx , s .ds , height ); derr != nil {
124
126
err = errors .Join (err , fmt .Errorf ("setting tail to %d: %w" , height , derr ))
125
127
}
126
128
}()
127
129
130
+ deleteCtx := ctx
128
131
if deadline , ok := ctx .Deadline (); ok {
129
132
// allocate 95% of caller's set deadline for deletion
130
133
// and give leftover to save progress
131
134
// this prevents store's state corruption from partial deletion
132
135
sub := deadline .Sub (startTime ) / 100 * 95
133
136
var cancel context.CancelFunc
134
- ctx , cancel = context .WithDeadlineCause (ctx , startTime .Add (sub ), errDeleteTimeout )
137
+ deleteCtx , cancel = context .WithDeadlineCause (ctx , startTime .Add (sub ), errDeleteTimeout )
135
138
defer cancel ()
136
139
}
137
140
138
141
if to - from < deleteRangeParallelThreshold {
139
- height , err = s .deleteSequential (ctx , from , to )
142
+ height , err = s .deleteSequential (deleteCtx , from , to )
140
143
} else {
141
- height , err = s .deleteParallel (ctx , from , to )
144
+ height , err = s .deleteParallel (deleteCtx , from , to )
142
145
}
143
146
144
147
return err
@@ -159,7 +162,7 @@ func (s *Store[H]) deleteSingle(
159
162
160
163
hash , err := s .heightIndex .HashByHeight (ctx , height , false )
161
164
if errors .Is (err , datastore .ErrNotFound ) {
162
- log .Warnw ("attempt to delete header that's not found" , "height" , height )
165
+ log .Debugw ("attempt to delete header that's not found" , "height" , height )
163
166
return nil
164
167
}
165
168
if err != nil {
@@ -219,19 +222,21 @@ func (s *Store[H]) deleteSequential(
219
222
// deleteParallel deletes [from:to) header range from the store in parallel
220
223
// and returns the highest unprocessed height: 'to' in success case or the failed height in error case.
221
224
func (s * Store [H ]) deleteParallel (ctx context.Context , from , to uint64 ) (uint64 , error ) {
222
- log .Debugw ("starting delete range parallel" , "from_height" , from , "to_height" , to )
223
-
225
+ now := time .Now ()
224
226
s .onDeleteMu .Lock ()
225
227
onDelete := slices .Clone (s .onDelete )
226
228
s .onDeleteMu .Unlock ()
227
-
228
229
// workerNum defines how many parallel delete workers to run
229
230
// Scales of number of CPUs configured for the process.
230
231
// Usually, it's recommended to have 2-4 multiplier for the number of CPUs for
231
232
// IO operations. Three was picked empirically to be a sweet spot that doesn't
232
233
// require too much RAM, yet shows good performance.
233
234
workerNum := runtime .GOMAXPROCS (- 1 ) * 3
234
235
236
+ log .Infow (
237
+ "deleting range parallel" , "from_height" , from , "to_height" , to , "worker_num" , workerNum ,
238
+ )
239
+
235
240
type result struct {
236
241
height uint64
237
242
err error
@@ -245,7 +250,11 @@ func (s *Store[H]) deleteParallel(ctx context.Context, from, to uint64) (uint64,
245
250
defer func () {
246
251
results [worker ] = last
247
252
if last .err != nil {
248
- close (errCh )
253
+ select {
254
+ case <- errCh :
255
+ default :
256
+ close (errCh )
257
+ }
249
258
}
250
259
}()
251
260
@@ -277,11 +286,11 @@ func (s *Store[H]) deleteParallel(ctx context.Context, from, to uint64) (uint64,
277
286
}(i )
278
287
}
279
288
280
- for i , height := 0 , from ; height < to ; height ++ {
289
+ for i , height := uint64 ( 0 ) , from ; height < to ; height ++ {
281
290
select {
282
291
case jobCh <- height :
283
292
i ++
284
- if uint64 ( 1 ) % deleteRangeParallelThreshold == 0 {
293
+ if i % deleteRangeParallelThreshold == 0 {
285
294
log .Debugf ("deleting %dth header height %d" , deleteRangeParallelThreshold , height )
286
295
}
287
296
case <- errCh :
@@ -312,5 +321,14 @@ func (s *Store[H]) deleteParallel(ctx context.Context, from, to uint64) (uint64,
312
321
313
322
// ensures the height after the highest deleted becomes the new tail
314
323
highest ++
324
+ log .Infow (
325
+ "deleted range parallel" ,
326
+ "from_height" ,
327
+ from ,
328
+ "to_height" ,
329
+ to ,
330
+ "took(s)" ,
331
+ time .Since (now ).Seconds (),
332
+ )
315
333
return highest , nil
316
334
}
0 commit comments