Audacity  3.0.3
DBConnection.cpp
Go to the documentation of this file.
1 /*!********************************************************************
2 
3 Audacity: A Digital Audio Editor
4 
5 @file DBConnection.cpp
6 @brief Implements DBConnection
7 
8 Paul Licameli -- split from ProjectFileIO.cpp
9 
10 **********************************************************************/
11 
12 #include "DBConnection.h"
13 
14 #include "sqlite3.h"
15 
16 #include <wx/progdlg.h>
17 #include <wx/string.h>
18 
19 #include "AudacityLogger.h"
20 #include "FileNames.h"
21 #include "Internat.h"
22 #include "Project.h"
23 #include "FileException.h"
24 #include "wxFileNameWrapper.h"
25 
26 // Configuration to provide "safe" connections
27 static const char *SafeConfig =
28  "PRAGMA <schema>.busy_timeout = 5000;"
29  "PRAGMA <schema>.locking_mode = SHARED;"
30  "PRAGMA <schema>.synchronous = NORMAL;"
31  "PRAGMA <schema>.journal_mode = WAL;"
32  "PRAGMA <schema>.wal_autocheckpoint = 0;";
33 
34 // Configuration to provide "Fast" connections
35 static const char *FastConfig =
36  "PRAGMA <schema>.busy_timeout = 5000;"
37  "PRAGMA <schema>.locking_mode = SHARED;"
38  "PRAGMA <schema>.synchronous = OFF;"
39  "PRAGMA <schema>.journal_mode = OFF;";
40 
42  const std::weak_ptr<AudacityProject> &pProject,
43  const std::shared_ptr<DBConnectionErrors> &pErrors,
45 : mpProject{ pProject }
46 , mpErrors{ pErrors }
47 , mCallback{ std::move(callback) }
48 {
49  mDB = nullptr;
50  mCheckpointDB = nullptr;
51  mBypass = false;
52 }
53 
55 {
56  wxASSERT(mDB == nullptr);
57  if (mDB)
58  {
59  wxLogMessage("Database left open at connection destruction %s\n",
60  sqlite3_db_filename(mDB, nullptr));
61  }
62 }
63 
64 void DBConnection::SetBypass( bool bypass )
65 {
66  mBypass = bypass;
67 }
68 
70 {
71  return mBypass;
72 }
73 
75  const TranslatableString &msg, const TranslatableString &libraryError, int errorCode)
76 {
77  mpErrors->mErrorCode = errorCode;
78 
79  mpErrors->mLastError = msg;
80 
81  mpErrors->mLibraryError = errorCode && libraryError.empty()
82  ? XO("(%d): %s").Format(errorCode, sqlite3_errstr(errorCode))
83  : libraryError;
84 
85  wxLogMessage("DBConnection SetError\n"
86  "\tErrorCode: %d\n"
87  "\tLastError: %s\n"
88  "\tLibraryError: %s",
89  mpErrors->mErrorCode,
90  mpErrors->mLastError.Debug(),
91  mpErrors->mLibraryError.Debug());
92 
93  auto logger = AudacityLogger::Get();
94  if (logger)
95  {
96  mpErrors->mLog = logger->GetLog(10);
97  }
98 }
99 
101  const TranslatableString &msg, const TranslatableString &libraryError, int errorCode)
102 {
103  auto db = DB();
104 
105  mpErrors->mErrorCode = errorCode < 0 && db
106  ? sqlite3_errcode(db)
107  : errorCode;
108 
109  mpErrors->mLastError = msg.empty()
110  ? XO("(%d): %s").Format(mpErrors->mErrorCode, sqlite3_errstr(mpErrors->mErrorCode))
111  : msg;
112 
113  mpErrors->mLibraryError = libraryError.empty() && db
114  ? Verbatim(sqlite3_errmsg(db))
115  : libraryError;
116 
117  wxLogMessage("DBConnection SetDBError\n"
118  "\tErrorCode: %d\n"
119  "\tLastError: %s\n"
120  "\tLibraryError: %s",
121  mpErrors->mErrorCode,
122  mpErrors->mLastError.Debug(),
123  mpErrors->mLibraryError.Debug());
124 
125  auto logger = AudacityLogger::Get();
126  if (logger)
127  {
128  mpErrors->mLog = logger->GetLog(10);
129  }
130 }
131 
132 int DBConnection::Open(const FilePath fileName)
133 {
134  wxASSERT(mDB == nullptr);
135  int rc;
136 
137  // Initialize checkpoint controls
138  mCheckpointStop = false;
139  mCheckpointPending = false;
140  mCheckpointActive = false;
141  rc = OpenStepByStep( fileName );
142  if ( rc != SQLITE_OK)
143  {
144  if (mCheckpointDB)
145  {
146  sqlite3_close(mCheckpointDB);
147  mCheckpointDB = nullptr;
148  }
149 
150  if (mDB)
151  {
152  sqlite3_close(mDB);
153  mDB = nullptr;
154  }
155  }
156  return rc;
157 }
158 
160 {
161  const char *name = fileName.ToUTF8();
162 
163  bool success = false;
164  int rc = sqlite3_open(name, &mDB);
165  if (rc != SQLITE_OK) {
166  wxLogMessage("Failed to open primary connection to %s: %d, %s\n",
167  fileName,
168  rc,
169  sqlite3_errstr(rc));
170  return rc;
171  }
172 
173  // Set default mode
174  // (See comments in ProjectFileIO::SaveProject() about threading
175  rc = SafeMode();
176  if (rc != SQLITE_OK) {
177  SetDBError(XO("Failed to set safe mode on primary connection to %s").Format(fileName));
178  return rc;
179  }
180 
181  rc = sqlite3_open(name, &mCheckpointDB);
182  if (rc != SQLITE_OK) {
183  wxLogMessage("Failed to open checkpoint connection to %s: %d, %s\n",
184  fileName,
185  rc,
186  sqlite3_errstr(rc));
187  return rc;
188  }
189 
190  rc = ModeConfig(mCheckpointDB, "main", SafeConfig);
191  if (rc != SQLITE_OK) {
192  SetDBError(XO("Failed to set safe mode on checkpoint connection to %s").Format(fileName));
193  return rc;
194  }
195 
196  auto db = mCheckpointDB;
197  mCheckpointThread = std::thread(
198  [this, db, fileName]{ CheckpointThread(db, fileName); });
199 
200  // Install our checkpoint hook
201  sqlite3_wal_hook(mDB, CheckpointHook, this);
202  return rc;
203 }
204 
206 {
207  wxASSERT(mDB != nullptr);
208  int rc;
209 
210  // Protect...
211  if (mDB == nullptr)
212  {
213  return true;
214  }
215 
216  // Uninstall our checkpoint hook so that no additional checkpoints
217  // are sent our way. (Though this shouldn't really happen.)
218  sqlite3_wal_hook(mDB, nullptr, nullptr);
219 
220  // Display a progress dialog if there's active or pending checkpoints
222  {
223  TranslatableString title = XO("Checkpointing project");
224 
225  // Get access to the active project
226  auto project = mpProject.lock();
227  if (project)
228  {
229  title = XO("Checkpointing %s").Format(project->GetProjectName());
230  }
231 
232  // Provides a progress dialog with indeterminate mode
233  wxGenericProgressDialog pd(title.Translation(),
234  XO("This may take several seconds").Translation(),
235  300000, // range
236  nullptr, // parent
237  wxPD_APP_MODAL | wxPD_ELAPSED_TIME | wxPD_SMOOTH);
238 
239  // Wait for the checkpoints to end
241  {
242  wxMilliSleep(50);
243  pd.Pulse();
244  }
245  }
246 
247  // Tell the checkpoint thread to shutdown
248  {
249  std::lock_guard<std::mutex> guard(mCheckpointMutex);
250  mCheckpointStop = true;
251  mCheckpointCondition.notify_one();
252  }
253 
254  // And wait for it to do so
255  if (mCheckpointThread.joinable())
256  {
257  mCheckpointThread.join();
258  }
259 
260  // We're done with the prepared statements
261  {
262  std::lock_guard<std::mutex> guard(mStatementMutex);
263  for (auto stmt : mStatements)
264  {
265  // No need to process return code, but log it for diagnosis
266  rc = sqlite3_finalize(stmt.second);
267  if (rc != SQLITE_OK)
268  {
269  wxLogMessage("Failed to finalize statement on %s\n"
270  "\tErrMsg: %s\n"
271  "\tSQL: %s",
272  sqlite3_db_filename(mDB, nullptr),
273  sqlite3_errmsg(mDB),
274  stmt.second);
275  }
276  }
277  mStatements.clear();
278  }
279 
280  // Not much we can do if the closes fail, so just report the error
281 
282  // Close the checkpoint connection
283  rc = sqlite3_close(mCheckpointDB);
284  if (rc != SQLITE_OK)
285  {
286  wxLogMessage("Failed to close checkpoint connection for %s\n"
287  "\tError: %s\n",
288  sqlite3_db_filename(mCheckpointDB, nullptr),
289  sqlite3_errmsg(mCheckpointDB));
290  }
291  mCheckpointDB = nullptr;
292 
293  // Close the primary connection
294  rc = sqlite3_close(mDB);
295  if (rc != SQLITE_OK)
296  {
297  wxLogMessage("Failed to close %s\n"
298  "\tError: %s\n",
299  sqlite3_db_filename(mDB, nullptr),
300  sqlite3_errmsg(mDB));
301  }
302  mDB = nullptr;
303 
304  return true;
305 }
306 
307 [[noreturn]] void DBConnection::ThrowException( bool write ) const
308 {
309  // Sqlite3 documentation says returned character string
310  // does NOT require freeing by us.
311  wxString dbName{ sqlite3_db_filename(mDB, "main") };
312  // Now we have an absolute path. Throw a message box exception that
313  // formats a helpful message just as used to be done before sqlite3
314  // was used for projects.
315  throw FileException{
317  dbName
318  };
319 }
320 
321 int DBConnection::SafeMode(const char *schema /* = "main" */)
322 {
323  return ModeConfig(mDB, schema, SafeConfig);
324 }
325 
326 int DBConnection::FastMode(const char *schema /* = "main" */)
327 {
328  return ModeConfig(mDB, schema, FastConfig);
329 }
330 
331 int DBConnection::ModeConfig(sqlite3 *db, const char *schema, const char *config)
332 {
333  // Ensure attached DB connection gets configured
334  int rc;
335 
336  // Replace all schema "keywords" with the schema name
337  wxString sql = config;
338  sql.Replace(wxT("<schema>"), schema);
339 
340  // Set the configuration
341  rc = sqlite3_exec(db, sql, nullptr, nullptr, nullptr);
342  if (rc != SQLITE_OK)
343  {
344  // Don't store in connection, just report it
345  wxLogMessage("Failed to set mode on %s\n"
346  "\tError: %s\n"
347  "\tSQL: %s",
348  sqlite3_db_filename(mDB, nullptr),
349  sqlite3_errmsg(mDB),
350  sql);
351  }
352 
353  return rc;
354 }
355 
357 {
358  wxASSERT(mDB != nullptr);
359 
360  return mDB;
361 }
362 
364 {
365  return sqlite3_errcode(mDB);
366 }
367 
368 const wxString DBConnection::GetLastMessage() const
369 {
370  return sqlite3_errmsg(mDB);
371 }
372 
373 sqlite3_stmt *DBConnection::Prepare(enum StatementID id, const char *sql)
374 {
375  std::lock_guard<std::mutex> guard(mStatementMutex);
376 
377  int rc;
378  // See bug 2673
379  // We must not use the same prepared statement from two different threads.
380  // Therefore, in the cache, use the thread id too.
381  StatementIndex ndx(id, std::this_thread::get_id());
382 
383  // Return an existing statement if it's already been prepared
384  auto iter = mStatements.find(ndx);
385  if (iter != mStatements.end())
386  {
387  return iter->second;
388  }
389 
390  // Prepare the statement
391  sqlite3_stmt *stmt = nullptr;
392  rc = sqlite3_prepare_v3(mDB, sql, -1, SQLITE_PREPARE_PERSISTENT, &stmt, 0);
393  if (rc != SQLITE_OK)
394  {
395  wxLogMessage("Failed to prepare statement for %s\n"
396  "\tError: %s\n"
397  "\tSQL: %s",
398  sqlite3_db_filename(mDB, nullptr),
399  sqlite3_errmsg(mDB),
400  sql);
401 
402  // TODO: Look into why this causes an access violation
404  }
405 
406  // There are a small number (10 or so) of different id's corresponding
407  // to different SQL statements, see enum StatementID
408  // We have relatively few threads running at any one time,
409  // e.g. main gui thread, a playback thread, a thread for compacting.
410  // However the cache might keep growing, as we start/stop audio,
411  // perhaps, if we chose to use a new thread each time.
412  // For 3.0.0 I think that's OK. If it's a data leak it's a slow
413  // enough one. wxLogDebugs seem to show that the audio play thread
414  // is being reused, not recreated with a new ID, i.e. no leak at all.
415  // ANSWER-ME Just how serious is the data leak? How best to fix?
416 
417  // Remember the cached statement.
418  mStatements.insert({ndx, stmt});
419 
420  return stmt;
421 }
422 
423 void DBConnection::CheckpointThread(sqlite3 *db, const FilePath &fileName)
424 {
425  int rc = SQLITE_OK;
426  bool giveUp = false;
427 
428  while (true)
429  {
430  {
431  // Wait for work or the stop signal
432  std::unique_lock<std::mutex> lock(mCheckpointMutex);
433  mCheckpointCondition.wait(lock,
434  [&]
435  {
437  });
438 
439  // Requested to stop, so bail
440  if (mCheckpointStop)
441  {
442  break;
443  }
444 
445  // Capture the number of pages that need checkpointing and reset
446  mCheckpointActive = true;
447  mCheckpointPending = false;
448  }
449 
450  // And kick off the checkpoint. This may not checkpoint ALL frames
451  // in the WAL. They'll be gotten the next time around.
452  using namespace std::chrono;
453  do {
454  rc = giveUp ? SQLITE_OK :
455  sqlite3_wal_checkpoint_v2(
456  db, nullptr, SQLITE_CHECKPOINT_PASSIVE, nullptr, nullptr);
457  }
458  // Contentions for an exclusive lock on the database are possible,
459  // even while the main thread is merely drawing the tracks, which
460  // may perform reads
461  while (rc == SQLITE_BUSY && (std::this_thread::sleep_for(1ms), true));
462 
463  // Reset
464  mCheckpointActive = false;
465 
466  if (rc != SQLITE_OK)
467  {
468  wxLogMessage("Failed to perform checkpoint on %s\n"
469  "\tErrCode: %d\n"
470  "\tErrMsg: %s",
471  fileName,
472  sqlite3_errcode(db),
473  sqlite3_errmsg(db));
474 
475  // Can't checkpoint -- maybe the device has too little space
476  wxFileNameWrapper fName{ fileName };
477  auto path = FileNames::AbbreviatePath(fName);
478  auto name = fName.GetFullName();
479  auto longname = name + "-wal";
480 
481  // TODO: Should we return the actual error message if it's not a
482  // disk full condition?
483  auto message1 = rc == SQLITE_FULL
484  ? XO("Could not write to %s.\n").Format(path)
485  : TranslatableString{};
486  auto message = XO(
487  "Disk is full.\n"
488  "%s\n"
489  "For tips on freeing up space, click the help button."
490  ).Format(message1);
491 
492  // Stop trying to checkpoint
493  giveUp = true;
494 
495  // Stop the audio.
496  GuardedCall(
497  [&message] {
499  message, XO("Warning"), "Error:_Disk_full_or_not_writable" }; },
501  [this](AudacityException * e) {
502  // This executes in the main thread.
503  if (mCallback)
504  mCallback();
505  if (e)
506  e->DelayedHandlerAction();
507  }
508  );
509  }
510  }
511 
512  return;
513 }
514 
515 int DBConnection::CheckpointHook(void *data, sqlite3 *db, const char *schema, int pages)
516 {
517  // Get access to our object
518  DBConnection *that = static_cast<DBConnection *>(data);
519 
520  // Queue the database pointer for our checkpoint thread to process
521  std::lock_guard<std::mutex> guard(that->mCheckpointMutex);
522  that->mCheckpointPending = true;
523  that->mCheckpointCondition.notify_one();
524 
525  return SQLITE_OK;
526 }
527 
529 {
530  char *errmsg = nullptr;
531 
532  int rc = sqlite3_exec(mConnection.DB(),
533  wxT("SAVEPOINT ") + name + wxT(";"),
534  nullptr,
535  nullptr,
536  &errmsg);
537 
538  if (errmsg)
539  {
540  mConnection.SetDBError(
541  XO("Failed to create savepoint:\n\n%s").Format(name)
542  );
543  sqlite3_free(errmsg);
544  }
545 
546  return rc == SQLITE_OK;
547 }
548 
550 {
551  char *errmsg = nullptr;
552 
553  int rc = sqlite3_exec(mConnection.DB(),
554  wxT("RELEASE ") + name + wxT(";"),
555  nullptr,
556  nullptr,
557  &errmsg);
558 
559  if (errmsg)
560  {
561  mConnection.SetDBError(
562  XO("Failed to release savepoint:\n\n%s").Format(name)
563  );
564  sqlite3_free(errmsg);
565  }
566 
567  return rc == SQLITE_OK;
568 }
569 
571 {
572  char *errmsg = nullptr;
573 
574  int rc = sqlite3_exec(mConnection.DB(),
575  wxT("ROLLBACK TO ") + name + wxT(";"),
576  nullptr,
577  nullptr,
578  &errmsg);
579 
580  if (errmsg)
581  {
582  mConnection.SetDBError(
583  XO("Failed to release savepoint:\n\n%s").Format(name)
584  );
585  sqlite3_free(errmsg);
586  }
587 
588  return rc == SQLITE_OK;
589 }
590 
592  DBConnection &connection, const char *name)
593 : mConnection(connection),
594  mName(name)
595 {
597  if ( !mInTrans )
598  // To do, improve the message
600  XO("Database error. Sorry, but we don't have more details."),
601  XO("Warning"),
602  "Error:_Disk_full_or_not_writable"
603  );
604 }
605 
607 {
608  if (mInTrans)
609  {
610  // Rollback AND REMOVE the transaction
611  // -- must do both; rolling back a savepoint only rewinds it
612  // without removing it, unlike the ROLLBACK command
613  if (!(TransactionRollback(mName) &&
615  {
616  // Do not throw from a destructor!
617  // This has to be a no-fail cleanup that does the best that it can.
618  wxLogMessage("Transaction active at scope destruction");
619  }
620  }
621 }
622 
624 {
625  if ( !mInTrans )
626  {
627  wxLogMessage("No active transaction to commit");
628 
629  // Misuse of this class
631  }
632 
634 
635  return mInTrans;
636 }
637 
639 {
640  wxASSERT_MSG(!mpConnection, wxT("Project file was not closed at shutdown"));
641  if (mpConnection)
642  {
643  wxLogMessage("Project file was not closed at connection destruction");
644  }
645 }
646 
649  []( AudacityProject & ){
650  // Ignore the argument; this is just a holder of a
651  // unique_ptr to DBConnection, which must be filled in later
652  // (when we can get a weak_ptr to the project)
653  auto result = std::make_shared< ConnectionPtr >();
654  return result;
655  }
656 };
657 
659 {
660  auto &result =
661  project.AttachedObjects::Get< ConnectionPtr >( sConnectionPtrKey );
662  return result;
663 }
664 
666 {
667  return Get( const_cast< AudacityProject & >( project ) );
668 }
669 
TranslatableString
Definition: Types.h:290
DBConnection::Close
bool Close()
Definition: DBConnection.cpp:205
DBConnection::mCheckpointPending
std::atomic_bool mCheckpointPending
Definition: DBConnection.h:114
TranslatableString::empty
bool empty() const
Definition: Types.h:329
DBConnection::StatementID
StatementID
Definition: DBConnection.h:71
wxFileNameWrapper.h
sConnectionPtrKey
static const AudacityProject::AttachedObjects::RegisteredFactory sConnectionPtrKey
Definition: DBConnection.cpp:648
wxFileNameWrapper
Definition: wxFileNameWrapper.h:21
DBConnection::mDB
sqlite3 * mDB
Definition: DBConnection.h:107
Project.h
DBConnection::SetDBError
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.
Definition: DBConnection.cpp:100
FileException::Cause::Write
@ Write
most important to detect when storage space is exhausted
FileException::Cause::Read
@ Read
DBConnection::CheckpointFailureCallback
std::function< void()> CheckpointFailureCallback
Definition: DBConnection.h:43
Format
Abstract base class used in importing a file.
DBConnection::DBConnection
DBConnection(const std::weak_ptr< AudacityProject > &pProject, const std::shared_ptr< DBConnectionErrors > &pErrors, CheckpointFailureCallback callback)
Definition: DBConnection.cpp:41
TransactionScope::~TransactionScope
~TransactionScope()
Definition: DBConnection.cpp:606
FileException
Thrown for failure of file or database operations in deeply nested places.
Definition: FileException.h:18
DBConnection::Open
int Open(const FilePath fileName)
Definition: DBConnection.cpp:132
XO
#define XO(s)
Definition: Internat.h:32
DBConnection::GetLastRC
int GetLastRC() const
Definition: DBConnection.cpp:363
DBConnection::mCallback
CheckpointFailureCallback mCallback
Definition: DBConnection.h:122
ConnectionPtr::~ConnectionPtr
~ConnectionPtr() override
Definition: DBConnection.cpp:638
DBConnection.h
Declare DBConnection, which maintains database connection and associated status and background thread...
DBConnection
Definition: DBConnection.h:39
DBConnection::GetLastMessage
const wxString GetLastMessage() const
Definition: DBConnection.cpp:368
ClientData::Site::RegisteredFactory
Client code makes static instance from a factory of attachments; passes it to Get or Find as a retrie...
Definition: ClientData.h:266
DBConnection::SetBypass
void SetBypass(bool bypass)
Definition: DBConnection.cpp:64
FileException.h
MessageBoxException for failures of file operations.
DBConnection::DB
sqlite3 * DB()
Definition: DBConnection.cpp:356
SafeConfig
static const char * SafeConfig
Definition: DBConnection.cpp:27
TransactionScope::TransactionRollback
bool TransactionRollback(const wxString &name)
Definition: DBConnection.cpp:570
DBConnection::mCheckpointDB
sqlite3 * mCheckpointDB
Definition: DBConnection.h:108
AudacityException
Base class for exceptions specially processed by the application.
Definition: AudacityException.h:25
DBConnection::OpenStepByStep
int OpenStepByStep(const FilePath fileName)
Definition: DBConnection.cpp:159
DBConnection::mCheckpointCondition
std::condition_variable mCheckpointCondition
Definition: DBConnection.h:111
FastConfig
static const char * FastConfig
Definition: DBConnection.cpp:35
TransactionScope::TransactionCommit
bool TransactionCommit(const wxString &name)
Definition: DBConnection.cpp:549
TransactionScope::TransactionStart
bool TransactionStart(const wxString &name)
Definition: DBConnection.cpp:528
FileNames::AbbreviatePath
AUDACITY_DLL_API wxString AbbreviatePath(const wxFileName &fileName)
Give enough of the path to identify the device. (On Windows, drive letter plus ':')
name
const TranslatableString name
Definition: Distortion.cpp:98
AudacityLogger::Get
static AudacityLogger * Get()
Definition: AudacityLogger.cpp:58
ConnectionPtr
Definition: DBConnection.h:161
THROW_INCONSISTENCY_EXCEPTION
#define THROW_INCONSISTENCY_EXCEPTION
Throw InconsistencyException, using C++ preprocessor to identify the source code location.
Definition: InconsistencyException.h:77
TransactionScope::mName
wxString mName
Definition: DBConnection.h:149
DBConnection::ThrowException
void ThrowException(bool write) const
throw and show appropriate message box
Definition: DBConnection.cpp:307
DBConnection::mpErrors
std::shared_ptr< DBConnectionErrors > mpErrors
Definition: DBConnection.h:121
DBConnection::CheckpointHook
static int CheckpointHook(void *data, sqlite3 *db, const char *schema, int pages)
Definition: DBConnection.cpp:515
Internat.h
DBConnection::SetError
void SetError(const TranslatableString &msg, const TranslatableString &libraryError={}, int errorCode={})
Just set stored errors.
Definition: DBConnection.cpp:74
AudacityLogger.h
FilePath
wxString FilePath
Definition: Types.h:270
DBConnection::mCheckpointThread
std::thread mCheckpointThread
Definition: DBConnection.h:110
SimpleGuard< void >
Specialization of SimpleGuard, also defining a default value.
Definition: AudacityException.h:141
DBConnection::mCheckpointActive
std::atomic_bool mCheckpointActive
Definition: DBConnection.h:115
ConnectionPtr::Get
static ConnectionPtr & Get(AudacityProject &project)
Definition: DBConnection.cpp:658
AudacityProject
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:112
DBConnection::mBypass
bool mBypass
Definition: DBConnection.h:125
FileNames.h
Verbatim
TranslatableString Verbatim(wxString str)
Definition: Types.h:573
GuardedCall
R GuardedCall(const F1 &body, const F2 &handler=F2::Default(), const F3 &delayedHandler={})
Execute some code on any thread; catch any AudacityException; enqueue error report on the main thread...
Definition: AudacityException.h:187
DBConnection::ShouldBypass
bool ShouldBypass()
Definition: DBConnection.cpp:69
DBConnection::SafeMode
int SafeMode(const char *schema="main")
Definition: DBConnection.cpp:321
DBConnection::mCheckpointMutex
std::mutex mCheckpointMutex
Definition: DBConnection.h:112
DBConnection::ModeConfig
int ModeConfig(sqlite3 *db, const char *schema, const char *config)
Definition: DBConnection.cpp:331
ConnectionPtr::mpConnection
Connection mpConnection
Definition: DBConnection.h:168
DBConnection::CheckpointThread
void CheckpointThread(sqlite3 *db, const FilePath &fileName)
Definition: DBConnection.cpp:423
TranslatableString::Translation
wxString Translation() const
Definition: Types.h:337
TransactionScope::Commit
bool Commit()
Definition: DBConnection.cpp:623
DBConnection::~DBConnection
~DBConnection()
Definition: DBConnection.cpp:54
TransactionScope::mInTrans
bool mInTrans
Definition: DBConnection.h:148
DBConnection::mpProject
std::weak_ptr< AudacityProject > mpProject
Definition: DBConnection.h:106
DBConnection::mStatementMutex
std::mutex mStatementMutex
Definition: DBConnection.h:117
SimpleMessageBoxException
A MessageBoxException that shows a given, unvarying string.
Definition: AudacityException.h:78
DBConnection::mCheckpointStop
std::atomic_bool mCheckpointStop
Definition: DBConnection.h:113
DBConnection::mStatements
std::map< StatementIndex, sqlite3_stmt * > mStatements
Definition: DBConnection.h:119
DBConnection::Prepare
sqlite3_stmt * Prepare(enum StatementID id, const char *sql)
Definition: DBConnection.cpp:373
DBConnection::StatementIndex
std::pair< enum StatementID, std::thread::id > StatementIndex
Definition: DBConnection.h:118
TransactionScope::TransactionScope
TransactionScope(DBConnection &connection, const char *name)
Definition: DBConnection.cpp:591
DBConnection::FastMode
int FastMode(const char *schema="main")
Definition: DBConnection.cpp:326