static void _advance_time(gint timeout) { if (timeout) timer_wheel_set_time(pattern_db_get_timer_wheel(patterndb), timer_wheel_get_time(pattern_db_get_timer_wheel(patterndb)) + timeout + 1); }
void test_rule_action_message_tag(const gchar *pattern, gint timeout, gint ndx, const gchar *tag, gboolean set) { LogMessage *msg = log_msg_new_empty(); gboolean found, result; PDBInput input; log_msg_set_value(msg, LM_V_MESSAGE, pattern, strlen(pattern)); log_msg_set_value(msg, LM_V_PROGRAM, "prog2", 5); log_msg_set_value(msg, LM_V_HOST, MYHOST, strlen(MYHOST)); log_msg_set_value(msg, LM_V_PID, MYPID, strlen(MYPID)); msg->timestamps[LM_TS_STAMP].tv_sec = msg->timestamps[LM_TS_RECVD].tv_sec; result = pattern_db_process(patterndb, PDB_INPUT_WRAP_MESSAGE(&input, msg)); if (timeout) timer_wheel_set_time(patterndb->timer_wheel, timer_wheel_get_time(patterndb->timer_wheel) + timeout + 5); if (ndx >= messages->len) { test_fail("Expected the %d. message, but no such message was returned by patterndb\n", ndx); goto exit; } found = log_msg_is_tag_by_name((LogMessage *) g_ptr_array_index(messages, ndx), tag); if (set ^ found) test_fail("Tag '%s' is %sset for pattern '%s' (%d), index %d\n", tag, found ? "" : "not ", pattern, !!result, ndx); exit: log_msg_unref(msg); test_clean_state(); }
/* NOTE: lock should be acquired for writing before calling this function. */ static void _advance_time_based_on_message(PatternDB *self, PDBProcessParams *process_params, const LogStamp *ls) { GTimeVal now; /* clamp the current time between the timestamp of the current message * (low limit) and the current system time (high limit). This ensures * that incorrect clocks do not skew the current time know by the * correllation engine too much. */ cached_g_current_time(&now); self->last_tick = now; if (ls->tv_sec < now.tv_sec) now.tv_sec = ls->tv_sec; /* the expire callback uses this pointer to find the process_params it * needs to emit messages. ProcessParams itself is a per-thread value, * however the timer callback is executing with the writer lock held. * There's no other mechanism to pass this pointer to the timer callback, * so we add it to PatternDB, but make sure it is properly protected by * locks. * */ self->timer_process_params = process_params; timer_wheel_set_time(self->timer_wheel, now.tv_sec); self->timer_process_params = NULL; msg_debug("Advancing patterndb current time because of an incoming message", evt_tag_long("utc", timer_wheel_get_time(self->timer_wheel))); }
void pattern_db_advance_time(PatternDB *self, gint timeout) { PDBProcessParams process_params_p = {0}; PDBProcessParams *process_params = &process_params_p; time_t new_time; g_static_rw_lock_writer_lock(&self->lock); new_time = timer_wheel_get_time(self->timer_wheel) + timeout; self->timer_process_params = process_params; timer_wheel_set_time(self->timer_wheel, new_time); self->timer_process_params = NULL; g_static_rw_lock_writer_unlock(&self->lock); _flush_emitted_messages(self, process_params); }
/* * This function can be called any time when pattern-db is not processing * messages, but we expect the correllation timer to move forward. It * doesn't need to be called absolutely regularly as it'll use the current * system time to determine how much time has passed since the last * invocation. See the timing comment at pattern_db_process() for more * information. */ void pattern_db_timer_tick(PatternDB *self) { GTimeVal now; glong diff; PDBProcessParams process_params_p = {0}; PDBProcessParams *process_params = &process_params_p; g_static_rw_lock_writer_lock(&self->lock); self->timer_process_params = process_params; cached_g_current_time(&now); diff = g_time_val_diff(&now, &self->last_tick); if (diff > 1e6) { glong diff_sec = (glong) (diff / 1e6); timer_wheel_set_time(self->timer_wheel, timer_wheel_get_time(self->timer_wheel) + diff_sec); msg_debug("Advancing patterndb current time because of timer tick", evt_tag_long("utc", timer_wheel_get_time(self->timer_wheel))); /* update last_tick, take the fraction of the seconds not calculated into this update into account */ self->last_tick = now; g_time_val_add(&self->last_tick, - (glong)(diff - diff_sec * 1e6)); } else if (diff < 0) { /* time moving backwards, this can only happen if the computer's time * is changed. We don't update patterndb's idea of the time now, wait * another tick instead to update that instead. */ self->last_tick = now; } self->timer_process_params = NULL; g_static_rw_lock_writer_unlock(&self->lock); _flush_emitted_messages(self, process_params); }
void test_rule_action_message_value(const gchar *pattern, gint timeout, gint ndx, const gchar *name, const gchar *value) { LogMessage *msg = log_msg_new_empty(); gboolean found = FALSE, result; const gchar *val; gssize len; PDBInput input; log_msg_set_value(msg, LM_V_MESSAGE, pattern, strlen(pattern)); log_msg_set_value(msg, LM_V_PROGRAM, "prog2", 5); log_msg_set_value(msg, LM_V_HOST, MYHOST, strlen(MYHOST)); log_msg_set_value(msg, LM_V_PID, MYPID, strlen(MYPID)); msg->timestamps[LM_TS_STAMP].tv_sec = msg->timestamps[LM_TS_RECVD].tv_sec; result = pattern_db_process(patterndb, PDB_INPUT_WRAP_MESSAGE(&input, msg)); if (timeout) timer_wheel_set_time(patterndb->timer_wheel, timer_wheel_get_time(patterndb->timer_wheel) + timeout + 1); if (ndx >= messages->len) { test_fail("Expected the %d. message, but no such message was returned by patterndb\n", ndx); goto exit; } val = log_msg_get_value((LogMessage *) g_ptr_array_index(messages, ndx), log_msg_get_value_handle(name), &len); if (value) found = strcmp(val, value) == 0; if (!!value ^ (len > 0)) test_fail("Value '%s' is %smatching for pattern '%s' (%d) index %d\n", name, found ? "" : "not ", pattern, !!result, ndx); exit: log_msg_unref(msg); test_clean_state(); }
static void _advance_time(gint timeout) { if (timeout) timer_wheel_set_time(patterndb->timer_wheel, timer_wheel_get_time(patterndb->timer_wheel) + timeout + 1); }
void test_wheel(gint seed) { TimerWheel *wheel; gint i; guint64 latest = 0; gint expected_callbacks; prev_now = 0; num_callbacks = 0; expected_callbacks = 0; srand(seed); wheel = timer_wheel_new(); _test_assoc_data(wheel); timer_wheel_set_time(wheel, 1); for (i = 0; i < NUM_TIMERS; i++) { guint64 expires; TWEntry *timer1, *timer2, *timer3; gint r; expires = rand() & ((1 << 24) - 1); if (expires <= 1) expires = 1; if (expires > latest) latest = expires; timer1 = timer_wheel_add_timer(wheel, expires - 1, timer_callback, g_memdup(&expires, sizeof(expires)), (GDestroyNotify) g_free); timer2 = timer_wheel_add_timer(wheel, expires - 1, timer_callback, g_memdup(&expires, sizeof(expires)), (GDestroyNotify) g_free); timer3 = timer_wheel_add_timer(wheel, expires - 1, timer_callback, g_memdup(&expires, sizeof(expires)), (GDestroyNotify) g_free); expected_callbacks += 3; r = rand() & 0xFF; if (r < 64) { /* delete the timer with 25% chance */ timer_wheel_del_timer(wheel, timer1); expected_callbacks--; } else if (r < 128) { /* delete the timer with 25% chance */ timer_wheel_del_timer(wheel, timer2); expected_callbacks--; } else if (r < 192) { /* delete the timer with 25% chance */ timer_wheel_del_timer(wheel, timer3); expected_callbacks--; } } timer_wheel_set_time(wheel, latest + 1); if (num_callbacks != expected_callbacks) { fprintf(stderr, "Error: not enough callbacks received, " "num_callbacks=%d, expected=%d\n", num_callbacks, expected_callbacks); exit(1); } timer_wheel_free(wheel); }