/*! * \internal * \brief astdb sync thread * * This thread is in charge of syncing astdb to disk after a change. * By pushing it off to this thread to take care of, this I/O bound operation * will not block other threads from performing other critical processing. * If changes happen rapidly, this thread will also ensure that the sync * operations are rate limited. */ static void *db_sync_thread(void *data) { ast_mutex_lock(&dblock); ast_db_begin_transaction(); for (;;) { /* We're ok with spurious wakeups, so we don't worry about a predicate */ ast_cond_wait(&dbcond, &dblock); if (ast_db_commit_transaction()) { ast_db_rollback_transaction(); } if (doexit) { ast_mutex_unlock(&dblock); break; } ast_db_begin_transaction(); ast_mutex_unlock(&dblock); sleep(1); ast_mutex_lock(&dblock); /* Unfortunately, it is possible for signaling to happen * when we're not waiting: in the bit when we're unlocked * above. Do the do-exit check here again. (We could do * it once, but that would impose a forced delay of 1 * second always.) */ if (doexit) { ast_mutex_unlock(&dblock); break; } } return NULL; }
/*! * \internal * \brief astdb sync thread * * This thread is in charge of syncing astdb to disk after a change. * By pushing it off to this thread to take care of, this I/O bound operation * will not block other threads from performing other critical processing. * If changes happen rapidly, this thread will also ensure that the sync * operations are rate limited. */ static void *db_sync_thread(void *data) { ast_mutex_lock(&dblock); ast_db_begin_transaction(); for (;;) { /* If dosync is set, db_sync() was called during sleep(1), * and the pending transaction should be committed. * Otherwise, block until db_sync() is called. */ while (!dosync) { ast_cond_wait(&dbcond, &dblock); } dosync = 0; if (ast_db_commit_transaction()) { ast_db_rollback_transaction(); } if (doexit) { ast_mutex_unlock(&dblock); break; } ast_db_begin_transaction(); ast_mutex_unlock(&dblock); sleep(1); ast_mutex_lock(&dblock); } return NULL; }