27#define AUDACITY_PROJECT_PAGE_SIZE 65536
38 "PRAGMA <schema>.busy_timeout = 5000;"
39 "PRAGMA <schema>.locking_mode = SHARED;"
40 "PRAGMA <schema>.synchronous = NORMAL;"
41 "PRAGMA <schema>.journal_mode = WAL;"
42 "PRAGMA <schema>.wal_autocheckpoint = 0;";
46 "PRAGMA <schema>.busy_timeout = 5000;"
47 "PRAGMA <schema>.locking_mode = SHARED;"
48 "PRAGMA <schema>.synchronous = OFF;"
49 "PRAGMA <schema>.journal_mode = OFF;";
52 const std::weak_ptr<AudacityProject> &pProject,
53 const std::shared_ptr<DBConnectionErrors> &pErrors,
55: mpProject{ pProject }
57, mCallback{
std::move(callback) }
66 wxASSERT(
mDB ==
nullptr);
69 wxLogMessage(
"Database left open at connection destruction %s\n",
70 sqlite3_db_filename(
mDB,
nullptr));
92 ?
XO(
"(%d): %s").Format(errorCode, sqlite3_errstr(errorCode))
95 wxLogMessage(
"DBConnection SetError\n"
106 mpErrors->mLog = logger->GetLog(10);
115 mpErrors->mErrorCode = errorCode < 0 && db
116 ? sqlite3_errcode(db)
127 wxLogMessage(
"DBConnection SetDBError\n"
130 "\tLibraryError: %s",
138 mpErrors->mLog = logger->GetLog(10);
144 wxASSERT(
mDB ==
nullptr);
152 if ( rc != SQLITE_OK)
171 const char *
name = fileName.ToUTF8();
173 bool success =
false;
174 int rc = sqlite3_open(
name, &
mDB);
180 wxLogMessage(
"Failed to open primary connection to %s: %d, %s\n",
191 SetDBError(
XO(
"Failed to set page size for database %s")
201 SetDBError(
XO(
"Failed to set safe mode on primary connection to %s").
Format(fileName));
211 wxLogMessage(
"Failed to open checkpoint connection to %s: %d, %s\n",
219 if (rc != SQLITE_OK) {
220 SetDBError(
XO(
"Failed to set safe mode on checkpoint connection to %s").
Format(fileName));
235 wxASSERT(
mDB !=
nullptr);
246 sqlite3_wal_hook(
mDB,
nullptr,
nullptr);
263 title,
XO(
"This may take several seconds"));
269 using namespace std::chrono;
270 std::this_thread::sleep_for(50ms);
294 rc = sqlite3_finalize(stmt.second);
297 wxLogMessage(
"Failed to finalize statement on %s\n"
300 sqlite3_db_filename(
mDB,
nullptr),
317 wxLogMessage(
"Failed to close checkpoint connection for %s\n"
325 rc = sqlite3_close(
mDB);
331 wxLogMessage(
"Failed to close %s\n"
333 sqlite3_db_filename(
mDB,
nullptr),
334 sqlite3_errmsg(
mDB));
345 wxString dbName{ sqlite3_db_filename(
mDB,
"main") };
373 sqlite3_stmt *stmt =
nullptr;
374 int rc = sqlite3_prepare_v2(
mDB,
"SELECT EXISTS(SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'project')", -1, &stmt,
nullptr);
378 auto finalizer =
finally([&stmt] { sqlite3_finalize(stmt); });
379 rc = sqlite3_step(stmt);
380 if (rc == SQLITE_ROW)
382 if (sqlite3_column_int (stmt, 0) == 1)
399 wxString sql = config;
400 sql.Replace(
wxT(
"<schema>"), schema);
403 rc = sqlite3_exec(db, sql,
nullptr,
nullptr,
nullptr);
411 wxLogMessage(
"Failed to set mode on %s\n"
414 sqlite3_db_filename(
mDB,
nullptr),
424 wxASSERT(
mDB !=
nullptr);
431 return sqlite3_errcode(
mDB);
436 return sqlite3_errmsg(
mDB);
457 sqlite3_stmt *stmt =
nullptr;
458 rc = sqlite3_prepare_v3(
mDB, sql, -1, SQLITE_PREPARE_PERSISTENT, &stmt, 0);
465 wxLogMessage(
"Failed to prepare statement for %s\n"
468 sqlite3_db_filename(
mDB,
nullptr),
522 using namespace std::chrono;
524 rc = giveUp ? SQLITE_OK :
525 sqlite3_wal_checkpoint_v2(
526 db,
nullptr, SQLITE_CHECKPOINT_PASSIVE,
nullptr,
nullptr);
531 while (rc == SQLITE_BUSY && (std::this_thread::sleep_for(1ms),
true));
541 wxLogMessage(
"Failed to perform checkpoint on %s\n"
551 auto name = fName.GetFullName();
552 auto longname =
name +
"-wal";
556 auto message1 = rc == SQLITE_FULL
557 ?
XO(
"Could not write to %s.\n").Format(path)
571 message,
XO(
"Warning"),
"Error:_Disk_full_or_not_writable" }; },
578 e->DelayedHandlerAction();
617 if (
auto pConnection = connectionPtr.mpConnection.get())
619 std::make_unique<DBConnectionTransactionScopeImpl>(*pConnection);
628 char *errmsg =
nullptr;
644 sqlite3_free(errmsg);
647 return rc == SQLITE_OK;
652 char *errmsg =
nullptr;
668 sqlite3_free(errmsg);
671 return rc == SQLITE_OK;
676 char *errmsg =
nullptr;
691 sqlite3_free(errmsg);
706 wxASSERT_MSG(!
mpConnection,
wxT(
"Project file was not closed at shutdown"));
709 wxLogMessage(
"Project file was not closed at connection destruction");
719 auto result = std::make_shared< ConnectionPtr >();
@ BadEnvironment
Indicates problems with environment, such as a full disk.
@ Internal
Indicates internal failure from Audacity.
R GuardedCall(const F1 &body, const F2 &handler=F2::Default(), F3 delayedHandler=DefaultDelayedHandlerAction) noexcept(noexcept(handler(std::declval< AudacityException * >())) &&noexcept(handler(nullptr)) &&noexcept(std::function< void(AudacityException *)>{std::move(delayedHandler)}))
Execute some code on any thread; catch any AudacityException; enqueue error report on the main thread...
Toolkit-neutral facade for basic user interface services.
#define AUDACITY_PROJECT_PAGE_SIZE
static const char * PageSizeConfig
static const char * SafeConfig
static const AudacityProject::AttachedObjects::RegisteredFactory sConnectionPtrKey
static const char * FastConfig
static TransactionScope::Factory::Scope scope
Declare DBConnection, which maintains database connection and associated status and background thread...
MessageBoxException for failures of file operations.
#define THROW_INCONSISTENCY_EXCEPTION
Throw InconsistencyException, using C++ preprocessor to identify the source code location.
#define ADD_EXCEPTION_CONTEXT(name, value)
TranslatableString Verbatim(wxString str)
Require calls to the one-argument constructor to go through this distinct global function name.
Base class for exceptions specially processed by the application.
static AudacityLogger * Get()
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Client code makes static instance from a factory of attachments; passes it to Get or Find as a retrie...
~ConnectionPtr() override
static ConnectionPtr & Get(AudacityProject &project)
void CheckpointThread(sqlite3 *db, const FilePath &fileName)
std::shared_ptr< DBConnectionErrors > mpErrors
static int CheckpointHook(void *data, sqlite3 *db, const char *schema, int pages)
std::mutex mCheckpointMutex
void ThrowException(bool write) const
throw and show appropriate message box
int OpenStepByStep(const FilePath fileName)
void SetError(const TranslatableString &msg, const TranslatableString &libraryError={}, int errorCode={})
Just set stored errors.
const wxString GetLastMessage() const
std::atomic_bool mCheckpointStop
std::atomic_bool mCheckpointActive
std::mutex mStatementMutex
std::atomic_bool mCheckpointPending
int FastMode(const char *schema="main")
std::thread mCheckpointThread
void SetBypass(bool bypass)
sqlite3_stmt * Prepare(enum StatementID id, const char *sql)
int SetPageSize(const char *schema="main")
DBConnection(const std::weak_ptr< AudacityProject > &pProject, const std::shared_ptr< DBConnectionErrors > &pErrors, CheckpointFailureCallback callback)
std::condition_variable mCheckpointCondition
std::map< StatementIndex, sqlite3_stmt * > mStatements
void SetDBError(const TranslatableString &msg, const TranslatableString &libraryError={}, int errorCode=-1)
Set stored errors and write to log; and default libraryError to what database library reports.
int ModeConfig(sqlite3 *db, const char *schema, const char *config)
std::function< void()> CheckpointFailureCallback
std::weak_ptr< AudacityProject > mpProject
CheckpointFailureCallback mCallback
int Open(const FilePath fileName)
std::pair< enum StatementID, std::thread::id > StatementIndex
int SafeMode(const char *schema="main")
Thrown for failure of file or database operations in deeply nested places.
@ Write
most important to detect when storage space is exhausted
typename GlobalVariable< Factory, const std::function< std::unique_ptr< TransactionScopeImpl > >, nullptr, Options... >::Scope Scope
A MessageBoxException that shows a given, unvarying string.
Abstract base class for implementation of steps of TransactionScope.
Holds a msgid for the translation catalog; may also bind format arguments.
std::unique_ptr< GenericProgressDialog > MakeGenericProgress(const WindowPlacement &placement, const TranslatableString &title, const TranslatableString &message, int style=(ProgressAppModal|ProgressShowElapsedTime|ProgressSmooth))
Create and display a progress dialog (return nullptr if Services not installed)
FILES_API wxString AbbreviatePath(const wxFileName &fileName)
Give enough of the path to identify the device. (On Windows, drive letter plus ':')
~DBConnectionTransactionScopeImpl() override
bool TransactionCommit(const wxString &name) override
bool TransactionRollback(const wxString &name) override
DBConnection & mConnection
DBConnectionTransactionScopeImpl(DBConnection &connection)
bool TransactionStart(const wxString &name) override
Specialization of SimpleGuard, also defining a default value.