| 491 | } |
| 492 | |
| 493 | void DBConnection::CheckpointThread(sqlite3 *db, const FilePath &fileName) |
| 494 | { |
| 495 | int rc = SQLITE_OK; |
| 496 | bool giveUp = false; |
| 497 | |
| 498 | while (true) |
| 499 | { |
| 500 | { |
| 501 | // Wait for work or the stop signal |
| 502 | std::unique_lock<std::mutex> lock(mCheckpointMutex); |
| 503 | mCheckpointCondition.wait(lock, |
| 504 | [&] |
| 505 | { |
| 506 | return mCheckpointPending || mCheckpointStop; |
| 507 | }); |
| 508 | |
| 509 | // Requested to stop, so bail |
| 510 | if (mCheckpointStop) |
| 511 | { |
| 512 | break; |
| 513 | } |
| 514 | |
| 515 | // Capture the number of pages that need checkpointing and reset |
| 516 | mCheckpointActive = true; |
| 517 | mCheckpointPending = false; |
| 518 | } |
| 519 | |
| 520 | // And kick off the checkpoint. This may not checkpoint ALL frames |
| 521 | // in the WAL. They'll be gotten the next time around. |
| 522 | using namespace std::chrono; |
| 523 | do { |
| 524 | rc = giveUp ? SQLITE_OK : |
| 525 | sqlite3_wal_checkpoint_v2( |
| 526 | db, nullptr, SQLITE_CHECKPOINT_PASSIVE, nullptr, nullptr); |
| 527 | } |
| 528 | // Contentions for an exclusive lock on the database are possible, |
| 529 | // even while the main thread is merely drawing the tracks, which |
| 530 | // may perform reads |
| 531 | while (rc == SQLITE_BUSY && (std::this_thread::sleep_for(1ms), true)); |
| 532 | |
| 533 | // Reset |
| 534 | mCheckpointActive = false; |
| 535 | |
| 536 | if (rc != SQLITE_OK) |
| 537 | { |
| 538 | ADD_EXCEPTION_CONTEXT("sqlite3.rc", std::to_string(rc)); |
| 539 | ADD_EXCEPTION_CONTEXT("sqlite3.context", "DBConnection::CheckpointThread"); |
| 540 | |
| 541 | wxLogMessage("Failed to perform checkpoint on %s\n" |
| 542 | "\tErrCode: %d\n" |
| 543 | "\tErrMsg: %s", |
| 544 | fileName, |
| 545 | sqlite3_errcode(db), |
| 546 | sqlite3_errmsg(db)); |
| 547 | |
| 548 | // Can't checkpoint -- maybe the device has too little space |
| 549 | wxFileNameWrapper fName{ fileName }; |
| 550 | auto path = FileNames::AbbreviatePath(fName); |
nothing calls this directly
no test coverage detected