Audacity 3.2.0
Public Types | Public Member Functions | Private Types | Private Member Functions | Static Private Member Functions | Private Attributes | List of all members
DBConnection Class Referencefinal

#include <DBConnection.h>

Collaboration diagram for DBConnection:
[legend]

Public Types

enum  StatementID {
  GetSamples , GetSummary256 , GetSummary64k , LoadSampleBlock ,
  InsertSampleBlock , DeleteSampleBlock , GetSampleBlockSize , GetAllSampleBlocksSize
}
 
using CheckpointFailureCallback = std::function< void()>
 

Public Member Functions

 DBConnection (const std::weak_ptr< AudacityProject > &pProject, const std::shared_ptr< DBConnectionErrors > &pErrors, CheckpointFailureCallback callback)
 
 ~DBConnection ()
 
int Open (const FilePath fileName)
 
bool Close ()
 
void ThrowException (bool write) const
 throw and show appropriate message box More...
 
int SafeMode (const char *schema="main")
 
int FastMode (const char *schema="main")
 
int SetPageSize (const char *schema="main")
 
bool Assign (sqlite3 *handle)
 
sqlite3 * Detach ()
 
sqlite3 * DB ()
 
int GetLastRC () const
 
const wxString GetLastMessage () const
 
sqlite3_stmt * Prepare (enum StatementID id, const char *sql)
 
void SetBypass (bool bypass)
 
bool ShouldBypass ()
 
void SetError (const TranslatableString &msg, const TranslatableString &libraryError={}, int errorCode={})
 Just set stored errors. More...
 
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. More...
 

Private Types

using StatementIndex = std::pair< enum StatementID, std::thread::id >
 

Private Member Functions

int OpenStepByStep (const FilePath fileName)
 
int ModeConfig (sqlite3 *db, const char *schema, const char *config)
 
void CheckpointThread (sqlite3 *db, const FilePath &fileName)
 

Static Private Member Functions

static int CheckpointHook (void *data, sqlite3 *db, const char *schema, int pages)
 

Private Attributes

std::weak_ptr< AudacityProjectmpProject
 
sqlite3 * mDB
 
sqlite3 * mCheckpointDB
 
std::thread mCheckpointThread
 
std::condition_variable mCheckpointCondition
 
std::mutex mCheckpointMutex
 
std::atomic_bool mCheckpointStop { false }
 
std::atomic_bool mCheckpointPending { false }
 
std::atomic_bool mCheckpointActive { false }
 
std::mutex mStatementMutex
 
std::map< StatementIndex, sqlite3_stmt * > mStatements
 
std::shared_ptr< DBConnectionErrorsmpErrors
 
CheckpointFailureCallback mCallback
 
bool mBypass
 

Detailed Description

Definition at line 39 of file DBConnection.h.

Member Typedef Documentation

◆ CheckpointFailureCallback

using DBConnection::CheckpointFailureCallback = std::function<void()>

Definition at line 42 of file DBConnection.h.

◆ StatementIndex

using DBConnection::StatementIndex = std::pair<enum StatementID, std::thread::id>
private

Definition at line 122 of file DBConnection.h.

Member Enumeration Documentation

◆ StatementID

Enumerator
GetSamples 
GetSummary256 
GetSummary64k 
LoadSampleBlock 
InsertSampleBlock 
DeleteSampleBlock 
GetSampleBlockSize 
GetAllSampleBlocksSize 

Definition at line 74 of file DBConnection.h.

Constructor & Destructor Documentation

◆ DBConnection()

DBConnection::DBConnection ( const std::weak_ptr< AudacityProject > &  pProject,
const std::shared_ptr< DBConnectionErrors > &  pErrors,
CheckpointFailureCallback  callback 
)
Parameters
callbackInvoked in the main thread in idle time after detection of checkpoint failure, which might have been in a worker thread

Definition at line 51 of file DBConnection.cpp.

55: mpProject{ pProject }
56, mpErrors{ pErrors }
57, mCallback{ std::move(callback) }
58{
59 mDB = nullptr;
60 mCheckpointDB = nullptr;
61 mBypass = false;
62}
std::shared_ptr< DBConnectionErrors > mpErrors
Definition: DBConnection.h:125
sqlite3 * mCheckpointDB
Definition: DBConnection.h:112
sqlite3 * mDB
Definition: DBConnection.h:111
std::weak_ptr< AudacityProject > mpProject
Definition: DBConnection.h:110
CheckpointFailureCallback mCallback
Definition: DBConnection.h:126

References mBypass, mCheckpointDB, and mDB.

◆ ~DBConnection()

DBConnection::~DBConnection ( )

Definition at line 64 of file DBConnection.cpp.

65{
66 wxASSERT(mDB == nullptr);
67 if (mDB)
68 {
69 wxLogMessage("Database left open at connection destruction %s\n",
70 sqlite3_db_filename(mDB, nullptr));
71 }
72}

References mDB.

Member Function Documentation

◆ Assign()

bool DBConnection::Assign ( sqlite3 *  handle)

◆ CheckpointHook()

int DBConnection::CheckpointHook ( void *  data,
sqlite3 *  db,
const char *  schema,
int  pages 
)
staticprivate

Definition at line 587 of file DBConnection.cpp.

588{
589 // Get access to our object
590 DBConnection *that = static_cast<DBConnection *>(data);
591
592 // Queue the database pointer for our checkpoint thread to process
593 std::lock_guard<std::mutex> guard(that->mCheckpointMutex);
594 that->mCheckpointPending = true;
595 that->mCheckpointCondition.notify_one();
596
597 return SQLITE_OK;
598}
std::mutex mCheckpointMutex
Definition: DBConnection.h:116
std::atomic_bool mCheckpointPending
Definition: DBConnection.h:118
std::condition_variable mCheckpointCondition
Definition: DBConnection.h:115

References mCheckpointCondition, mCheckpointMutex, and mCheckpointPending.

Referenced by OpenStepByStep().

Here is the caller graph for this function:

◆ CheckpointThread()

void DBConnection::CheckpointThread ( sqlite3 *  db,
const FilePath fileName 
)
private

Definition at line 493 of file DBConnection.cpp.

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 {
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);
551 auto name = fName.GetFullName();
552 auto longname = name + "-wal";
553
554 // TODO: Should we return the actual error message if it's not a
555 // disk full condition?
556 auto message1 = rc == SQLITE_FULL
557 ? XO("Could not write to %s.\n").Format(path)
559 auto message = XO(
560 "Disk is full.\n"
561 "%s"
562 ).Format(message1);
563
564 // Stop trying to checkpoint
565 giveUp = true;
566
567 // Stop the audio.
569 [&message, rc] {
571 message, XO("Warning"), "Error:_Disk_full_or_not_writable" }; },
573 [this](AudacityException * e) {
574 // This executes in the main thread.
575 if (mCallback)
576 mCallback();
577 if (e)
578 e->DelayedHandlerAction();
579 }
580 );
581 }
582 }
583
584 return;
585}
@ 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...
const TranslatableString name
Definition: Distortion.cpp:76
XO("Cut/Copy/Paste")
#define ADD_EXCEPTION_CONTEXT(name, value)
Definition: SentryHelper.h:21
Base class for exceptions specially processed by the application.
std::atomic_bool mCheckpointStop
Definition: DBConnection.h:117
std::atomic_bool mCheckpointActive
Definition: DBConnection.h:119
A MessageBoxException that shows a given, unvarying string.
Holds a msgid for the translation catalog; may also bind format arguments.
FILES_API wxString AbbreviatePath(const wxFileName &fileName)
Give enough of the path to identify the device. (On Windows, drive letter plus ':')
Specialization of SimpleGuard, also defining a default value.

References FileNames::AbbreviatePath(), ADD_EXCEPTION_CONTEXT, BadEnvironment, GuardedCall(), Internal, mCallback, mCheckpointActive, mCheckpointCondition, mCheckpointMutex, mCheckpointPending, mCheckpointStop, name, and XO().

Referenced by OpenStepByStep().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ Close()

bool DBConnection::Close ( )

Definition at line 233 of file DBConnection.cpp.

234{
235 wxASSERT(mDB != nullptr);
236 int rc;
237
238 // Protect...
239 if (mDB == nullptr)
240 {
241 return true;
242 }
243
244 // Uninstall our checkpoint hook so that no additional checkpoints
245 // are sent our way. (Though this shouldn't really happen.)
246 sqlite3_wal_hook(mDB, nullptr, nullptr);
247
248 // Display a progress dialog if there's active or pending checkpoints
250 {
251 TranslatableString title = XO("Checkpointing project");
252
253 // Get access to the active project
254 auto project = mpProject.lock();
255 if (project)
256 {
257 title = XO("Checkpointing %s").Format(project->GetProjectName());
258 }
259
260 // Provides a progress dialog with indeterminate mode
261 using namespace BasicUI;
262 auto pd = MakeGenericProgress({},
263 title, XO("This may take several seconds"));
264 wxASSERT(pd);
265
266 // Wait for the checkpoints to end
268 {
269 using namespace std::chrono;
270 std::this_thread::sleep_for(50ms);
271 pd->Pulse();
272 }
273 }
274
275 // Tell the checkpoint thread to shutdown
276 {
277 std::lock_guard<std::mutex> guard(mCheckpointMutex);
278 mCheckpointStop = true;
279 mCheckpointCondition.notify_one();
280 }
281
282 // And wait for it to do so
283 if (mCheckpointThread.joinable())
284 {
285 mCheckpointThread.join();
286 }
287
288 // We're done with the prepared statements
289 {
290 std::lock_guard<std::mutex> guard(mStatementMutex);
291 for (auto stmt : mStatements)
292 {
293 // No need to process return code, but log it for diagnosis
294 rc = sqlite3_finalize(stmt.second);
295 if (rc != SQLITE_OK)
296 {
297 wxLogMessage("Failed to finalize statement on %s\n"
298 "\tErrMsg: %s\n"
299 "\tSQL: %s",
300 sqlite3_db_filename(mDB, nullptr),
301 sqlite3_errmsg(mDB),
302 stmt.second);
303 }
304 }
305 mStatements.clear();
306 }
307
308 // Not much we can do if the closes fail, so just report the error
309
310 // Close the checkpoint connection
311 rc = sqlite3_close(mCheckpointDB);
312 if (rc != SQLITE_OK)
313 {
314 ADD_EXCEPTION_CONTEXT("sqlite3.rc", std::to_string(rc));
315 ADD_EXCEPTION_CONTEXT("sqlite3.context", "DBConnection::Close::close_checkpoint");
316
317 wxLogMessage("Failed to close checkpoint connection for %s\n"
318 "\tError: %s\n",
319 sqlite3_db_filename(mCheckpointDB, nullptr),
320 sqlite3_errmsg(mCheckpointDB));
321 }
322 mCheckpointDB = nullptr;
323
324 // Close the primary connection
325 rc = sqlite3_close(mDB);
326 if (rc != SQLITE_OK)
327 {
328 ADD_EXCEPTION_CONTEXT("sqlite3.rc", std::to_string(rc));
329 ADD_EXCEPTION_CONTEXT("sqlite3.context", "DBConnection::OpenStepByStep::close");
330
331 wxLogMessage("Failed to close %s\n"
332 "\tError: %s\n",
333 sqlite3_db_filename(mDB, nullptr),
334 sqlite3_errmsg(mDB));
335 }
336 mDB = nullptr;
337
338 return true;
339}
static const auto title
const auto project
std::mutex mStatementMutex
Definition: DBConnection.h:121
std::thread mCheckpointThread
Definition: DBConnection.h:114
std::map< StatementIndex, sqlite3_stmt * > mStatements
Definition: DBConnection.h:123
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:312

References ADD_EXCEPTION_CONTEXT, BasicUI::MakeGenericProgress(), mCheckpointActive, mCheckpointCondition, mCheckpointDB, mCheckpointMutex, mCheckpointPending, mCheckpointStop, mCheckpointThread, mDB, mpProject, mStatementMutex, mStatements, project, title, and XO().

Here is the call graph for this function:

◆ DB()

sqlite3 * DBConnection::DB ( )

Definition at line 422 of file DBConnection.cpp.

423{
424 wxASSERT(mDB != nullptr);
425
426 return mDB;
427}

References mDB.

Referenced by ProjectFileIO::DB(), SqliteSampleBlock::DB(), SetDBError(), DBConnectionTransactionScopeImpl::TransactionCommit(), DBConnectionTransactionScopeImpl::TransactionRollback(), and DBConnectionTransactionScopeImpl::TransactionStart().

Here is the caller graph for this function:

◆ Detach()

sqlite3 * DBConnection::Detach ( )

◆ FastMode()

int DBConnection::FastMode ( const char *  schema = "main")

Definition at line 360 of file DBConnection.cpp.

361{
362 return ModeConfig(mDB, schema, FastConfig);
363}
static const char * FastConfig
int ModeConfig(sqlite3 *db, const char *schema, const char *config)

References FastConfig, mDB, and ModeConfig().

Here is the call graph for this function:

◆ GetLastMessage()

const wxString DBConnection::GetLastMessage ( ) const

Definition at line 434 of file DBConnection.cpp.

435{
436 return sqlite3_errmsg(mDB);
437}

References mDB.

◆ GetLastRC()

int DBConnection::GetLastRC ( ) const

Definition at line 429 of file DBConnection.cpp.

430{
431 return sqlite3_errcode(mDB);
432}

References mDB.

◆ ModeConfig()

int DBConnection::ModeConfig ( sqlite3 *  db,
const char *  schema,
const char *  config 
)
private

Definition at line 393 of file DBConnection.cpp.

394{
395 // Ensure attached DB connection gets configured
396 int rc;
397
398 // Replace all schema "keywords" with the schema name
399 wxString sql = config;
400 sql.Replace(wxT("<schema>"), schema);
401
402 // Set the configuration
403 rc = sqlite3_exec(db, sql, nullptr, nullptr, nullptr);
404 if (rc != SQLITE_OK)
405 {
406 ADD_EXCEPTION_CONTEXT("sqlite3.rc", std::to_string(rc));
407 ADD_EXCEPTION_CONTEXT("sqlite3.context", "DBConnection::ModeConfig");
408 ADD_EXCEPTION_CONTEXT("sqlite3.mode", config);
409
410 // Don't store in connection, just report it
411 wxLogMessage("Failed to set mode on %s\n"
412 "\tError: %s\n"
413 "\tSQL: %s",
414 sqlite3_db_filename(mDB, nullptr),
415 sqlite3_errmsg(mDB),
416 sql);
417 }
418
419 return rc;
420}
wxT("CloseDown"))

References ADD_EXCEPTION_CONTEXT, mDB, and wxT().

Referenced by FastMode(), OpenStepByStep(), SafeMode(), and SetPageSize().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ Open()

int DBConnection::Open ( const FilePath  fileName)

Definition at line 142 of file DBConnection.cpp.

143{
144 wxASSERT(mDB == nullptr);
145 int rc;
146
147 // Initialize checkpoint controls
148 mCheckpointStop = false;
149 mCheckpointPending = false;
150 mCheckpointActive = false;
151 rc = OpenStepByStep( fileName );
152 if ( rc != SQLITE_OK)
153 {
154 if (mCheckpointDB)
155 {
156 sqlite3_close(mCheckpointDB);
157 mCheckpointDB = nullptr;
158 }
159
160 if (mDB)
161 {
162 sqlite3_close(mDB);
163 mDB = nullptr;
164 }
165 }
166 return rc;
167}
int OpenStepByStep(const FilePath fileName)

References mCheckpointActive, mCheckpointDB, mCheckpointPending, mCheckpointStop, mDB, and OpenStepByStep().

Here is the call graph for this function:

◆ OpenStepByStep()

int DBConnection::OpenStepByStep ( const FilePath  fileName)
private

Definition at line 169 of file DBConnection.cpp.

170{
171 const char *name = fileName.ToUTF8();
172
173 bool success = false;
174 int rc = sqlite3_open(name, &mDB);
175 if (rc != SQLITE_OK)
176 {
177 ADD_EXCEPTION_CONTEXT("sqlite3.rc", std::to_string(rc));
178 ADD_EXCEPTION_CONTEXT("sqlite3.context", "DBConnection::OpenStepByStep::open");
179
180 wxLogMessage("Failed to open primary connection to %s: %d, %s\n",
181 fileName,
182 rc,
183 sqlite3_errstr(rc));
184 return rc;
185 }
186
187 rc = SetPageSize();
188
189 if (rc != SQLITE_OK)
190 {
191 SetDBError(XO("Failed to set page size for database %s")
192 .Format(fileName));
193 return rc;
194 }
195
196 // Set default mode
197 // (See comments in ProjectFileIO::SaveProject() about threading
198 rc = SafeMode();
199 if (rc != SQLITE_OK)
200 {
201 SetDBError(XO("Failed to set safe mode on primary connection to %s").Format(fileName));
202 return rc;
203 }
204
205 rc = sqlite3_open(name, &mCheckpointDB);
206 if (rc != SQLITE_OK)
207 {
208 ADD_EXCEPTION_CONTEXT("sqlite3.rc", std::to_string(rc));
209 ADD_EXCEPTION_CONTEXT("sqlite3.context", "DBConnection::OpenStepByStep::open_checkpoint");
210
211 wxLogMessage("Failed to open checkpoint connection to %s: %d, %s\n",
212 fileName,
213 rc,
214 sqlite3_errstr(rc));
215 return rc;
216 }
217
218 rc = ModeConfig(mCheckpointDB, "main", SafeConfig);
219 if (rc != SQLITE_OK) {
220 SetDBError(XO("Failed to set safe mode on checkpoint connection to %s").Format(fileName));
221 return rc;
222 }
223
224 auto db = mCheckpointDB;
225 mCheckpointThread = std::thread(
226 [this, db, fileName]{ CheckpointThread(db, fileName); });
227
228 // Install our checkpoint hook
229 sqlite3_wal_hook(mDB, CheckpointHook, this);
230 return rc;
231}
static const char * SafeConfig
void CheckpointThread(sqlite3 *db, const FilePath &fileName)
static int CheckpointHook(void *data, sqlite3 *db, const char *schema, int pages)
int SetPageSize(const char *schema="main")
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 SafeMode(const char *schema="main")
Abstract base class used in importing a file.

References ADD_EXCEPTION_CONTEXT, CheckpointHook(), CheckpointThread(), mCheckpointDB, mCheckpointThread, mDB, ModeConfig(), name, SafeConfig, SafeMode(), SetDBError(), SetPageSize(), and XO().

Referenced by Open().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ Prepare()

sqlite3_stmt * DBConnection::Prepare ( enum StatementID  id,
const char *  sql 
)

Definition at line 439 of file DBConnection.cpp.

440{
441 std::lock_guard<std::mutex> guard(mStatementMutex);
442
443 int rc;
444 // See bug 2673
445 // We must not use the same prepared statement from two different threads.
446 // Therefore, in the cache, use the thread id too.
447 StatementIndex ndx(id, std::this_thread::get_id());
448
449 // Return an existing statement if it's already been prepared
450 auto iter = mStatements.find(ndx);
451 if (iter != mStatements.end())
452 {
453 return iter->second;
454 }
455
456 // Prepare the statement
457 sqlite3_stmt *stmt = nullptr;
458 rc = sqlite3_prepare_v3(mDB, sql, -1, SQLITE_PREPARE_PERSISTENT, &stmt, 0);
459 if (rc != SQLITE_OK)
460 {
461 ADD_EXCEPTION_CONTEXT("sqlite3.query", sql);
462 ADD_EXCEPTION_CONTEXT("sqlite3.rc", std::to_string(rc));
463 ADD_EXCEPTION_CONTEXT("sqlite3.context", "DBConnection::Prepare");
464
465 wxLogMessage("Failed to prepare statement for %s\n"
466 "\tError: %s\n"
467 "\tSQL: %s",
468 sqlite3_db_filename(mDB, nullptr),
469 sqlite3_errmsg(mDB),
470 sql);
471
472 // TODO: Look into why this causes an access violation
474 }
475
476 // There are a small number (10 or so) of different id's corresponding
477 // to different SQL statements, see enum StatementID
478 // We have relatively few threads running at any one time,
479 // e.g. main gui thread, a playback thread, a thread for compacting.
480 // However the cache might keep growing, as we start/stop audio,
481 // perhaps, if we chose to use a new thread each time.
482 // For 3.0.0 I think that's OK. If it's a data leak it's a slow
483 // enough one. wxLogDebugs seem to show that the audio play thread
484 // is being reused, not recreated with a new ID, i.e. no leak at all.
485 // ANSWER-ME Just how serious is the data leak? How best to fix?
486
487 // Remember the cached statement.
488 mStatements.insert({ndx, stmt});
489
490 return stmt;
491}
#define THROW_INCONSISTENCY_EXCEPTION
Throw InconsistencyException, using C++ preprocessor to identify the source code location.
std::pair< enum StatementID, std::thread::id > StatementIndex
Definition: DBConnection.h:122

References ADD_EXCEPTION_CONTEXT, mDB, mStatementMutex, mStatements, and THROW_INCONSISTENCY_EXCEPTION.

Referenced by SqliteSampleBlock::Commit(), SqliteSampleBlock::Delete(), SqliteSampleBlock::DoGetSamples(), ProjectFileIO::GetDiskUsage(), SqliteSampleBlock::GetSummary(), and SqliteSampleBlock::Load().

Here is the caller graph for this function:

◆ SafeMode()

int DBConnection::SafeMode ( const char *  schema = "main")

Definition at line 355 of file DBConnection.cpp.

356{
357 return ModeConfig(mDB, schema, SafeConfig);
358}

References mDB, ModeConfig(), and SafeConfig.

Referenced by OpenStepByStep().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ SetBypass()

void DBConnection::SetBypass ( bool  bypass)

Definition at line 74 of file DBConnection.cpp.

75{
76 mBypass = bypass;
77}

References mBypass.

◆ SetDBError()

void DBConnection::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 at line 110 of file DBConnection.cpp.

112{
113 auto db = DB();
114
115 mpErrors->mErrorCode = errorCode < 0 && db
116 ? sqlite3_errcode(db)
117 : errorCode;
118
119 mpErrors->mLastError = msg.empty()
120 ? XO("(%d): %s").Format(mpErrors->mErrorCode, sqlite3_errstr(mpErrors->mErrorCode))
121 : msg;
122
123 mpErrors->mLibraryError = libraryError.empty() && db
124 ? Verbatim(sqlite3_errmsg(db))
125 : libraryError;
126
127 wxLogMessage("DBConnection SetDBError\n"
128 "\tErrorCode: %d\n"
129 "\tLastError: %s\n"
130 "\tLibraryError: %s",
131 mpErrors->mErrorCode,
132 mpErrors->mLastError.Debug(),
133 mpErrors->mLibraryError.Debug());
134
135 auto logger = AudacityLogger::Get();
136 if (logger)
137 {
138 mpErrors->mLog = logger->GetLog(10);
139 }
140}
TranslatableString Verbatim(wxString str)
Require calls to the one-argument constructor to go through this distinct global function name.
static AudacityLogger * Get()
sqlite3 * DB()

References DB(), TranslatableString::empty(), AudacityLogger::Get(), mpErrors, Verbatim(), and XO().

Referenced by OpenStepByStep(), DBConnectionTransactionScopeImpl::TransactionCommit(), DBConnectionTransactionScopeImpl::TransactionRollback(), and DBConnectionTransactionScopeImpl::TransactionStart().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ SetError()

void DBConnection::SetError ( const TranslatableString msg,
const TranslatableString libraryError = {},
int  errorCode = {} 
)

Just set stored errors.

Definition at line 84 of file DBConnection.cpp.

86{
87 mpErrors->mErrorCode = errorCode;
88
89 mpErrors->mLastError = msg;
90
91 mpErrors->mLibraryError = errorCode && libraryError.empty()
92 ? XO("(%d): %s").Format(errorCode, sqlite3_errstr(errorCode))
93 : libraryError;
94
95 wxLogMessage("DBConnection SetError\n"
96 "\tErrorCode: %d\n"
97 "\tLastError: %s\n"
98 "\tLibraryError: %s",
99 mpErrors->mErrorCode,
100 mpErrors->mLastError.Debug(),
101 mpErrors->mLibraryError.Debug());
102
103 auto logger = AudacityLogger::Get();
104 if (logger)
105 {
106 mpErrors->mLog = logger->GetLog(10);
107 }
108}

References TranslatableString::empty(), AudacityLogger::Get(), mpErrors, and XO().

Here is the call graph for this function:

◆ SetPageSize()

int DBConnection::SetPageSize ( const char *  schema = "main")

Definition at line 365 of file DBConnection.cpp.

366{
367 // First of all - let's check if the database is empty.
368 // Otherwise, VACUUM can take a significant amount of time.
369 // VACUUM is required to force SQLite3 to change the page size.
370 // This function will be the first called on the connection,
371 // so if DB is empty we can assume that journal was not
372 // set to WAL yet.
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);
375
376 if (rc == SQLITE_OK)
377 {
378 auto finalizer = finally([&stmt] { sqlite3_finalize(stmt); });
379 rc = sqlite3_step(stmt);
380 if (rc == SQLITE_ROW)
381 {
382 if (sqlite3_column_int (stmt, 0) == 1)
383 {
384 // Project table exists, too late to VACUUM now
385 return SQLITE_OK;
386 }
387 }
388 }
389
390 return ModeConfig(mDB, schema, PageSizeConfig);
391}
static const char * PageSizeConfig

References mDB, ModeConfig(), and PageSizeConfig.

Referenced by OpenStepByStep().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ShouldBypass()

bool DBConnection::ShouldBypass ( )

Definition at line 79 of file DBConnection.cpp.

80{
81 return mBypass;
82}

References mBypass.

◆ ThrowException()

void DBConnection::ThrowException ( bool  write) const

throw and show appropriate message box

Parameters
writeIf true, a database update failed; if false, only a SELECT failed

Definition at line 341 of file DBConnection.cpp.

342{
343 // Sqlite3 documentation says returned character string
344 // does NOT require freeing by us.
345 wxString dbName{ sqlite3_db_filename(mDB, "main") };
346 // Now we have an absolute path. Throw a message box exception that
347 // formats a helpful message just as used to be done before sqlite3
348 // was used for projects.
349 throw FileException{
351 dbName
352 };
353}
Thrown for failure of file or database operations in deeply nested places.
Definition: FileException.h:19
@ Write
most important to detect when storage space is exhausted

References mDB, FileException::Read, and FileException::Write.

Referenced by SqliteSampleBlock::Commit(), SqliteSampleBlock::Delete(), SqliteSampleBlock::GetBlob(), ProjectFileIO::GetDiskUsage(), and SqliteSampleBlock::Load().

Here is the caller graph for this function:

Member Data Documentation

◆ mBypass

bool DBConnection::mBypass
private

Definition at line 129 of file DBConnection.h.

Referenced by DBConnection(), SetBypass(), and ShouldBypass().

◆ mCallback

CheckpointFailureCallback DBConnection::mCallback
private

Definition at line 126 of file DBConnection.h.

Referenced by CheckpointThread().

◆ mCheckpointActive

std::atomic_bool DBConnection::mCheckpointActive { false }
private

Definition at line 119 of file DBConnection.h.

Referenced by CheckpointThread(), Close(), and Open().

◆ mCheckpointCondition

std::condition_variable DBConnection::mCheckpointCondition
private

Definition at line 115 of file DBConnection.h.

Referenced by CheckpointHook(), CheckpointThread(), and Close().

◆ mCheckpointDB

sqlite3* DBConnection::mCheckpointDB
private

Definition at line 112 of file DBConnection.h.

Referenced by Close(), DBConnection(), Open(), and OpenStepByStep().

◆ mCheckpointMutex

std::mutex DBConnection::mCheckpointMutex
private

Definition at line 116 of file DBConnection.h.

Referenced by CheckpointHook(), CheckpointThread(), and Close().

◆ mCheckpointPending

std::atomic_bool DBConnection::mCheckpointPending { false }
private

Definition at line 118 of file DBConnection.h.

Referenced by CheckpointHook(), CheckpointThread(), Close(), and Open().

◆ mCheckpointStop

std::atomic_bool DBConnection::mCheckpointStop { false }
private

Definition at line 117 of file DBConnection.h.

Referenced by CheckpointThread(), Close(), and Open().

◆ mCheckpointThread

std::thread DBConnection::mCheckpointThread
private

Definition at line 114 of file DBConnection.h.

Referenced by Close(), and OpenStepByStep().

◆ mDB

sqlite3* DBConnection::mDB
private

◆ mpErrors

std::shared_ptr<DBConnectionErrors> DBConnection::mpErrors
private

Definition at line 125 of file DBConnection.h.

Referenced by SetDBError(), and SetError().

◆ mpProject

std::weak_ptr<AudacityProject> DBConnection::mpProject
private

Definition at line 110 of file DBConnection.h.

Referenced by Close().

◆ mStatementMutex

std::mutex DBConnection::mStatementMutex
private

Definition at line 121 of file DBConnection.h.

Referenced by Close(), and Prepare().

◆ mStatements

std::map<StatementIndex, sqlite3_stmt *> DBConnection::mStatements
private

Definition at line 123 of file DBConnection.h.

Referenced by Close(), and Prepare().


The documentation for this class was generated from the following files: