static void test_rewind_over_eof(LogQueueDiskReliable *dq) { LogMessage *msg3 = log_msg_new_mark(); LogMessage *read_message3; LogPathOptions local_options = LOG_PATH_OPTIONS_INIT; msg3->ack_func = _dummy_ack; log_queue_push_tail(&dq->super.super, msg3, &local_options); gint64 previous_read_head = dq->super.qdisk->hdr->read_head; read_message3 = log_queue_pop_head(&dq->super.super, &local_options); assert_true(read_message3 != NULL, ASSERTION_ERROR("Can't read message from queue")); assert_gint(dq->super.qdisk->hdr->read_head, dq->super.qdisk->hdr->write_head, ASSERTION_ERROR("Read head in bad position")); assert_true(msg3 == read_message3, ASSERTION_ERROR("Message 3 isn't read from qreliable")); log_msg_unref(read_message3); log_queue_rewind_backlog(&dq->super.super, 1); assert_gint(dq->super.qdisk->hdr->read_head, previous_read_head, ASSERTION_ERROR("Read head is corrupted")); read_message3 = log_queue_pop_head(&dq->super.super, &local_options); assert_true(read_message3 != NULL, ASSERTION_ERROR("Can't read message from queue")); assert_gint(dq->super.qdisk->hdr->read_head, dq->super.qdisk->hdr->write_head, ASSERTION_ERROR("Read head in bad position")); assert_true(msg3 == read_message3, ASSERTION_ERROR("Message 3 isn't read from qreliable")); log_msg_drop(msg3, &local_options, AT_PROCESSED); }
void log_threaded_dest_driver_message_rewind(LogThrDestDriver *self, LogMessage *msg) { log_queue_rewind_backlog(self->queue, 1); log_msg_unref(msg); }
/** * afsql_dd_begin_txn: * * Commit SQL transaction. * * NOTE: This function can only be called from the database thread. **/ static gboolean afsql_dd_commit_txn(AFSqlDestDriver *self, gboolean lock) { gboolean success; success = afsql_dd_run_query(self, "COMMIT", FALSE, NULL); if (lock) g_mutex_lock(self->db_thread_mutex); /* FIXME: this is a workaround because of the non-proper locking semantics * of the LogQueue. It might happen that the _queue() method sees 0 * elements in the queue, while the thread is still busy processing the * previous message. In that case arming the parallel push callback is * not needed and will cause assertions to fail. This is ugly and should * be fixed by properly defining the "blocking" semantics of the LogQueue * object w/o having to rely on user-code messing with parallel push * callbacks. */ log_queue_reset_parallel_push(self->queue); if (success) { log_queue_ack_backlog(self->queue, self->flush_lines_queued); } else { msg_notice("SQL transaction commit failed, rewinding backlog and starting again", NULL); log_queue_rewind_backlog(self->queue); } if (lock) g_mutex_unlock(self->db_thread_mutex); self->flush_lines_queued = 0; return success; }
static inline void afsql_dd_rollback_msg(AFSqlDestDriver *self, LogMessage *msg, LogPathOptions *path_options) { if (self->flags & AFSQL_DDF_EXPLICIT_COMMITS) log_queue_rewind_backlog(self->queue, 1); else log_queue_push_head(self->queue, msg, path_options); }
void test_rewind_backlog_without_using_qbacklog(LogQueueDiskReliable *dq, gint64 old_read_pos) { /* * Rewind the last 2 messages * - the read_head should be moved to the good position * - the qbacklog and qreliable should be untouched */ log_queue_rewind_backlog(&dq->super.super, 2); assert_gint64(dq->super.qdisk->hdr->read_head, old_read_pos + mark_message_serialized_size, ASSERTION_ERROR("Bad reader position")); assert_gint(dq->qreliable->length, 0, ASSERTION_ERROR("Incorrect number of items in the qreliable")); assert_gint(dq->qbacklog->length, NUMBER_MESSAGES_IN_QUEUE(3), ASSERTION_ERROR("Incorrect number of items in the qbacklog")); }
void test_rewind_backlog_partially_used_qbacklog(LogQueueDiskReliable *dq, gint64 old_read_pos) { /* * Rewind more 2 messages * - the reader the should be moved to the good position * - the qreliable should contain 1 items * - the qbackbacklog should contain 2 items */ log_queue_rewind_backlog(&dq->super.super, 2); assert_gint64(dq->super.qdisk->hdr->read_head, old_read_pos - mark_message_serialized_size, ASSERTION_ERROR("Bad reader position")); assert_gint(dq->qreliable->length, NUMBER_MESSAGES_IN_QUEUE(1), ASSERTION_ERROR("Incorrect number of items in the qreliable")); assert_gint(dq->qbacklog->length, NUMBER_MESSAGES_IN_QUEUE(2), ASSERTION_ERROR("Incorrect number of items in the qbacklog")); }
void test_rewind_backlog_use_whole_qbacklog(LogQueueDiskReliable *dq) { /* * Rewind more 2 messages * - the reader the should be moved to the backlog head * - the qreliable should contain 3 items * - the qbackbacklog should be empty */ log_queue_rewind_backlog(&dq->super.super, 2); assert_gint64(dq->super.qdisk->hdr->read_head, dq->super.qdisk->hdr->backlog_head, ASSERTION_ERROR("Bad reader position")); assert_gint(dq->qreliable->length, NUMBER_MESSAGES_IN_QUEUE(3), ASSERTION_ERROR("Incorrect number of items in the qreliable")); assert_gint(dq->qbacklog->length, 0, ASSERTION_ERROR("Incorrect number of items in the qbacklog")); }
/** * afsql_dd_begin_txn: * * Commit SQL transaction. * * NOTE: This function can only be called from the database thread. **/ static gboolean afsql_dd_commit_txn(AFSqlDestDriver *self) { gboolean success; success = afsql_dd_run_query(self, "COMMIT", FALSE, NULL); if (success) { log_queue_ack_backlog(self->queue, self->flush_lines_queued); } else { msg_notice("SQL transaction commit failed, rewinding backlog and starting again", NULL); log_queue_rewind_backlog(self->queue); } self->flush_lines_queued = 0; return success; }
/** * afsql_dd_handle_transaction_error: * * Handle errors inside during a SQL transaction (e.g. INSERT or COMMIT failures). * * NOTE: This function can only be called from the database thread. **/ static void afsql_dd_handle_transaction_error(AFSqlDestDriver *self) { log_queue_rewind_backlog(self->queue); self->flush_lines_queued = 0; }
void rewind_messages(LogQueue *q) { log_queue_rewind_backlog(q); }