/** * 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 void test_ack_over_eof(LogQueueDiskReliable *dq, LogMessage *msg1, LogMessage *msg2) { log_queue_ack_backlog(&dq->super.super, 3); assert_gint(dq->qbacklog->length, 0, ASSERTION_ERROR("Messages are in the qbacklog")); assert_gint(dq->super.qdisk->hdr->backlog_head, dq->super.qdisk->hdr->read_head, ASSERTION_ERROR("Backlog head in bad position")); }
void log_threaded_dest_driver_message_accept(LogThrDestDriver *self, LogMessage *msg) { self->retries.counter = 0; step_sequence_number(&self->seq_num); log_queue_ack_backlog(self->queue, 1); log_msg_unref(msg); }
/* * The method make the following situation * the backlog contains 6 messages * the qbacklog contains 3 messages, * but messages in qbacklog are the end of the backlog */ void _prepare_rewind_backlog_test(LogQueueDiskReliable *dq, gint64 *start_pos) { gint i; for (i = 0; i < 8; i++) { LogPathOptions path_options = LOG_PATH_OPTIONS_INIT; LogMessage *mark_message; mark_message = log_msg_new_mark(); mark_message->ack_func = _dummy_ack; log_queue_push_tail(&dq->super.super, mark_message, &path_options); } /* Lets read the messages and leave them in the backlog */ for (i = 0; i < 8; i++) { LogMessage *msg; LogPathOptions path_options = LOG_PATH_OPTIONS_INIT; msg = log_queue_pop_head(&dq->super.super, &path_options); log_msg_unref(msg); } /* Ack the messages which are not in the qbacklog */ log_queue_ack_backlog(&dq->super.super, 5); assert_gint(dq->qbacklog->length, NUMBER_MESSAGES_IN_QUEUE(3), ASSERTION_ERROR("Incorrect number of items in the qbacklog")); *start_pos = dq->super.qdisk->hdr->read_head; /* Now write 3 more messages and read them from buffer * the number of messages in the qbacklog should not be changed * The backlog should contain 6 messages * from these 6 messages 3 messages are cached in the qbacklog * No readable messages are in the queue */ for (i = 0; i < 3; i++) { LogPathOptions path_options = LOG_PATH_OPTIONS_INIT; LogMessage *mark_message; mark_message = log_msg_new_mark(); mark_message->ack_func = _dummy_ack; log_queue_push_tail(&dq->super.super, mark_message, &path_options); mark_message = log_queue_pop_head(&dq->super.super, &path_options); 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")); log_msg_unref(mark_message); } assert_gint(dq->super.qdisk->hdr->backlog_len, 6, ASSERTION_ERROR("Incorrect number of messages in the backlog")); assert_gint(dq->super.qdisk->hdr->length, 0, ASSERTION_ERROR("Reliable diskq isn't empty")); }
/** * 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); self->flush_lines_queued = 0; } else { msg_error("SQL transaction commit failed, rewinding backlog and starting again", NULL); afsql_dd_handle_transaction_error(self); } return success; }
Test(logqueue, test_zero_diskbuf_and_normal_acks) { LogQueue *q; gint i; q = log_queue_fifo_new(OVERFLOW_SIZE, NULL); StatsClusterKey sc_key; stats_lock(); stats_cluster_logpipe_key_set(&sc_key, SCS_DESTINATION, q->persist_name, NULL ); stats_register_counter(0, &sc_key, SC_TYPE_QUEUED, &q->queued_messages); stats_register_counter(1, &sc_key, SC_TYPE_MEMORY_USAGE, &q->memory_usage); stats_unlock(); log_queue_set_use_backlog(q, TRUE); cr_assert_eq(atomic_gssize_racy_get(&q->queued_messages->value), 0); fed_messages = 0; acked_messages = 0; feed_some_messages(q, 1); cr_assert_eq(stats_counter_get(q->queued_messages), 1); cr_assert_neq(stats_counter_get(q->memory_usage), 0); gint size_when_single_msg = stats_counter_get(q->memory_usage); for (i = 0; i < 10; i++) feed_some_messages(q, 10); cr_assert_eq(stats_counter_get(q->queued_messages), 101); cr_assert_eq(stats_counter_get(q->memory_usage), 101*size_when_single_msg); send_some_messages(q, fed_messages); log_queue_ack_backlog(q, fed_messages); cr_assert_eq(fed_messages, acked_messages, "did not receive enough acknowledgements: fed_messages=%d, acked_messages=%d", fed_messages, acked_messages); log_queue_unref(q); }
Test(logqueue, test_zero_diskbuf_alternating_send_acks) { LogQueue *q; gint i; q = log_queue_fifo_new(OVERFLOW_SIZE, NULL); log_queue_set_use_backlog(q, TRUE); fed_messages = 0; acked_messages = 0; for (i = 0; i < 10; i++) { feed_some_messages(q, 10); send_some_messages(q, 10); log_queue_ack_backlog(q, 10); } cr_assert_eq(fed_messages, acked_messages, "did not receive enough acknowledgements: fed_messages=%d, acked_messages=%d", fed_messages, acked_messages); log_queue_unref(q); }
static void log_writer_msg_ack(gint num_msg_acked, gpointer user_data) { LogWriter *self = (LogWriter *)user_data; log_queue_ack_backlog(self->queue, num_msg_acked); }
void app_ack_some_messages(LogQueue *q, gint n) { log_queue_ack_backlog(q, n); }