checkpointAllNoteboxes ensures that what's on-disk is up to date
(ctx context.Context, purge bool)
| 393 | |
| 394 | // checkpointAllNoteboxes ensures that what's on-disk is up to date |
| 395 | func checkpointAllNoteboxes(ctx context.Context, purge bool) error { |
| 396 | var firstError error |
| 397 | |
| 398 | // Collect all instances to checkpoint while holding the lock |
| 399 | // This prevents instances from being deleted while we're working |
| 400 | var toCheckpoint []struct { |
| 401 | storage interface{} |
| 402 | instance *NoteboxInstance |
| 403 | } |
| 404 | |
| 405 | // First pass: collect instances under lock |
| 406 | boxLock.RLock() |
| 407 | openboxes.Range(func(boxStorage, boxi interface{}) bool { |
| 408 | instance, ok := boxi.(*NoteboxInstance) |
| 409 | if ok && instance != nil { |
| 410 | toCheckpoint = append(toCheckpoint, struct { |
| 411 | storage interface{} |
| 412 | instance *NoteboxInstance |
| 413 | }{boxStorage, instance}) |
| 414 | } |
| 415 | return true |
| 416 | }) |
| 417 | boxLock.RUnlock() |
| 418 | |
| 419 | // Second pass: checkpoint each instance |
| 420 | for _, item := range toCheckpoint { |
| 421 | // Re-verify the instance is still in the map |
| 422 | currentInstance, stillExists := openboxes.Load(item.storage) |
| 423 | if !stillExists || currentInstance != item.instance { |
| 424 | // Instance was replaced or deleted, skip it |
| 425 | continue |
| 426 | } |
| 427 | |
| 428 | box := &Notebox{} |
| 429 | box.instance = item.instance |
| 430 | |
| 431 | emptyBox, err := box.checkpoint(ctx, true, purge, false, false) |
| 432 | if firstError == nil && err != nil && err.Error() != "notebox instance is nil" { |
| 433 | firstError = err |
| 434 | } |
| 435 | |
| 436 | // If we're purging, get rid of the notefile if it wasn't in use |
| 437 | if purge && emptyBox && err == nil { |
| 438 | // Use boxLock to ensure atomic purge |
| 439 | boxLock.Lock() |
| 440 | // Double-check it still exists and is the same instance |
| 441 | currentInstance, stillExists := openboxes.Load(item.storage) |
| 442 | if stillExists && currentInstance == item.instance { |
| 443 | openboxes.Delete(item.storage) |
| 444 | if debugBox { |
| 445 | logDebug(ctx, "Notebox %s purged", item.storage) |
| 446 | } |
| 447 | } |
| 448 | boxLock.Unlock() |
| 449 | } |
| 450 | } |
| 451 | |
| 452 | // Done |