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