[PATCH] Fix "make rpm" for a dirty source tree.
by Russell Bryant
If there are local changes, "make rpm" fails. This is because the
tarball that gets exported doesn't have "-dirty" in it. This is one
possible fix. The other is to change the name of the tarball.
Signed-off-by: Russell Bryant <rbryant(a)redhat.com>
---
libqb.spec.in | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/libqb.spec.in b/libqb.spec.in
index f734656..bc287c3 100644
--- a/libqb.spec.in
+++ b/libqb.spec.in
@@ -10,7 +10,7 @@ Summary: An IPC library for high performance servers.
Group: System Environment/Libraries
License: LGPLv2+
URL: http://www.libqb.org
-Source0: https://fedorahosted.org/releases/q/u/quarterback/%{name}-%{version}%{?nu...
+Source0: https://fedorahosted.org/releases/q/u/quarterback/%{name}-%{version}%{?nu...
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
BuildRequires: autoconf automake libtool doxygen procps check-devel
@@ -20,7 +20,7 @@ libqb provides high performance client server reusable features.
Initially these are IPC and poll.
%prep
-%setup -q -n %{name}-%{version}%{?numcomm:.%{numcomm}}%{?alphatag:-%{alphatag}}%{?dirty:-%{dirty}}
+%setup -q -n %{name}-%{version}%{?numcomm:.%{numcomm}}%{?alphatag:-%{alphatag}}
%build
./autogen.sh
--
1.7.7.6
12 years, 1 month
[PATCH] Revert part of my COARSE grained timer commit
by Angus Salkeld
The stopwatch and timers use qb_util_nano_current_get()
and need to be accurate. This does't seem to effect
performance at all so no loss there.
Signed-off-by: Angus Salkeld <asalkeld(a)redhat.com>
---
lib/util.c | 8 --------
1 files changed, 0 insertions(+), 8 deletions(-)
diff --git a/lib/util.c b/lib/util.c
index b5dcafe..a044368 100644
--- a/lib/util.c
+++ b/lib/util.c
@@ -142,11 +142,7 @@ qb_util_nano_current_get(void)
uint64_t nano_monotonic;
struct timespec ts;
-#ifdef CLOCK_MONOTONIC_COARSE
- clock_gettime(CLOCK_MONOTONIC_COARSE, &ts);
-#else
clock_gettime(CLOCK_MONOTONIC, &ts);
-#endif
nano_monotonic =
(ts.tv_sec * QB_TIME_NS_IN_SEC) + (uint64_t) ts.tv_nsec;
return (nano_monotonic);
@@ -173,11 +169,7 @@ qb_util_nano_monotonic_hz(void)
uint64_t nano_monotonic_hz;
struct timespec ts;
-#ifdef CLOCK_MONOTONIC_COARSE
- clock_getres(CLOCK_MONOTONIC_COARSE, &ts);
-#else
clock_getres(CLOCK_MONOTONIC, &ts);
-#endif
nano_monotonic_hz =
QB_TIME_NS_IN_SEC / ((ts.tv_sec * QB_TIME_NS_IN_SEC) + ts.tv_nsec);
--
1.7.7.6
12 years, 1 month
[PATCH 1/2] UTIL: if possible use COARSE resolution clocks - they are much faster.
by Angus Salkeld
Signed-off-by: Angus Salkeld <asalkeld(a)redhat.com>
---
lib/log.c | 4 ++--
lib/util.c | 20 +++++++++++++++++---
2 files changed, 19 insertions(+), 5 deletions(-)
diff --git a/lib/log.c b/lib/log.c
index 8879cfd..0101bc6 100644
--- a/lib/log.c
+++ b/lib/log.c
@@ -125,7 +125,7 @@ qb_log_real_va_(struct qb_log_callsite *cs, va_list ap)
{
int32_t found_threaded;
struct qb_log_target *t;
- struct timeval tv;
+ struct timespec tv;
int32_t pos;
int len;
int32_t formatted = QB_FALSE;
@@ -152,7 +152,7 @@ qb_log_real_va_(struct qb_log_callsite *cs, va_list ap)
}
}
- gettimeofday(&tv, NULL);
+ qb_util_timespec_from_epoch_get(&tv);
/*
* 1 if we can find a threaded target that needs this log then post it
diff --git a/lib/util.c b/lib/util.c
index b261f47..b5dcafe 100644
--- a/lib/util.c
+++ b/lib/util.c
@@ -142,8 +142,11 @@ qb_util_nano_current_get(void)
uint64_t nano_monotonic;
struct timespec ts;
+#ifdef CLOCK_MONOTONIC_COARSE
+ clock_gettime(CLOCK_MONOTONIC_COARSE, &ts);
+#else
clock_gettime(CLOCK_MONOTONIC, &ts);
-
+#endif
nano_monotonic =
(ts.tv_sec * QB_TIME_NS_IN_SEC) + (uint64_t) ts.tv_nsec;
return (nano_monotonic);
@@ -154,9 +157,11 @@ qb_util_nano_from_epoch_get(void)
{
uint64_t nano_monotonic;
struct timespec ts;
-
+#ifdef CLOCK_REALTIME_COARSE
+ clock_gettime(CLOCK_REALTIME_COARSE, &ts);
+#else
clock_gettime(CLOCK_REALTIME, &ts);
-
+#endif
nano_monotonic =
(ts.tv_sec * QB_TIME_NS_IN_SEC) + (uint64_t) ts.tv_nsec;
return (nano_monotonic);
@@ -168,7 +173,11 @@ qb_util_nano_monotonic_hz(void)
uint64_t nano_monotonic_hz;
struct timespec ts;
+#ifdef CLOCK_MONOTONIC_COARSE
+ clock_getres(CLOCK_MONOTONIC_COARSE, &ts);
+#else
clock_getres(CLOCK_MONOTONIC, &ts);
+#endif
nano_monotonic_hz =
QB_TIME_NS_IN_SEC / ((ts.tv_sec * QB_TIME_NS_IN_SEC) + ts.tv_nsec);
@@ -179,8 +188,13 @@ qb_util_nano_monotonic_hz(void)
void
qb_util_timespec_from_epoch_get(struct timespec *ts)
{
+#ifdef CLOCK_REALTIME_COARSE
+ clock_gettime(CLOCK_REALTIME_COARSE, ts);
+#else
clock_gettime(CLOCK_REALTIME, ts);
+#endif
}
+
#else
uint64_t
qb_util_nano_current_get(void)
--
1.7.7.6
12 years, 1 month
loop_poll.c:415 consumes 24576 bytes of ram
by Steven Dake
Angus,
I have found that loop_poll uses qb_array_create() (which does not
autogrow). Wouldn't this result in a ERANGE error on index for the poll
array?
I also noticed a full bin size is allocated. This makes sense (don't
want to realloc this array) but 256 elements (MAX_BIN_ELEMENTS) * a
large element size (such as 1k = very large memory consumption.
Seems like there is a determinism tradeoff between MAX_BIN and autogrow.
Are there other considerations?
I'd prefer lower memory usage for something like the loop_poll operation.
What are you thoughts about the tradeoff here (ie: do you have a strong
preference)?
One thing I also noticed was that the bin array was hard specified.
This makes sense if bin is small (256) but a reallocing bin would make
more sense if BIN_MAX was increased to something larger (like 2048 bin
elements).
12 years, 1 month
[PATCH] LOOP: add qb_loop_timer_is_running()
by Angus Salkeld
Signed-off-by: Angus Salkeld <asalkeld(a)redhat.com>
---
include/qb/qbloop.h | 10 ++++++++++
lib/loop_poll.c | 6 ++++++
tests/check_loop.c | 7 ++++++-
3 files changed, 22 insertions(+), 1 deletions(-)
diff --git a/include/qb/qbloop.h b/include/qb/qbloop.h
index 8fcd1b0..377e638 100644
--- a/include/qb/qbloop.h
+++ b/include/qb/qbloop.h
@@ -156,6 +156,16 @@ int32_t qb_loop_timer_add(qb_loop_t *l,
int32_t qb_loop_timer_del(qb_loop_t *l, qb_loop_timer_handle th);
/**
+ * Check to see if a timer that is still outstanding.
+ *
+ * @param l pointer to the loop instance
+ * @param th handle to delete the timer if needed.
+ * @retval QB_TRUE yes this timer is outstanding
+ * @retval QB_FALSE this timer does not exist or has expired
+ */
+int32_t qb_loop_timer_is_running(qb_loop_t *l, qb_loop_timer_handle th);
+
+/**
* Get the time remaining before it expires.
*
* @note if the timer has already expired it will return 0
diff --git a/lib/loop_poll.c b/lib/loop_poll.c
index 2f6fc20..7663101 100644
--- a/lib/loop_poll.c
+++ b/lib/loop_poll.c
@@ -875,6 +875,12 @@ qb_loop_timer_expire_time_get(struct qb_loop * lp, qb_loop_timer_handle th)
#endif /* HAVE_TIMERFD */
+int32_t
+qb_loop_timer_is_running(qb_loop_t *l, qb_loop_timer_handle th)
+{
+ return (qb_loop_timer_expire_time_get(l, th) > 0);
+}
+
static int32_t pipe_fds[2] = { -1, -1 };
struct qb_signal_source {
diff --git a/tests/check_loop.c b/tests/check_loop.c
index 4c022e9..7c54918 100644
--- a/tests/check_loop.c
+++ b/tests/check_loop.c
@@ -319,7 +319,7 @@ START_TEST(test_loop_timer_input)
}
END_TEST
-static void one_shot_tmo(void*data)
+static void one_shot_tmo(void * data)
{
static int32_t been_here = QB_FALSE;
ck_assert_int_eq(been_here, QB_FALSE);
@@ -335,6 +335,8 @@ static void reset_one_shot_tmo(void*data)
if (reset_timer_step == 0) {
res = qb_loop_timer_del(l, reset_th);
ck_assert_int_eq(res, -EINVAL);
+ res = qb_loop_timer_is_running(l, reset_th);
+ ck_assert_int_eq(res, QB_FALSE);
res = qb_loop_timer_add(l, QB_LOOP_LOW, 8*QB_TIME_NS_IN_MSEC, l, reset_one_shot_tmo, &reset_th);
ck_assert_int_eq(res, 0);
}
@@ -351,6 +353,9 @@ START_TEST(test_loop_timer_basic)
res = qb_loop_timer_add(l, QB_LOOP_LOW, 5*QB_TIME_NS_IN_MSEC, l, one_shot_tmo, &test_th);
ck_assert_int_eq(res, 0);
+ res = qb_loop_timer_is_running(l, test_th);
+ ck_assert_int_eq(res, QB_TRUE);
+
res = qb_loop_timer_add(l, QB_LOOP_LOW, 7*QB_TIME_NS_IN_MSEC, l, reset_one_shot_tmo, &reset_th);
ck_assert_int_eq(res, 0);
--
1.7.7.6
12 years, 1 month
[PATCH 1/3] LOG: add stdout target
by Angus Salkeld
Signed-off-by: Angus Salkeld <asalkeld(a)redhat.com>
---
examples/simplelog.c | 15 +++++++++++++--
include/qb/qblog.h | 1 +
lib/log.c | 4 +++-
lib/log_file.c | 9 +++++++--
4 files changed, 24 insertions(+), 5 deletions(-)
diff --git a/examples/simplelog.c b/examples/simplelog.c
index c0607c2..d5fbc0a 100644
--- a/examples/simplelog.c
+++ b/examples/simplelog.c
@@ -131,10 +131,11 @@ m_filter(struct qb_log_callsite *cs)
int32_t main(int32_t argc, char *argv[])
{
- const char *options = "vhtebdf:";
+ const char *options = "vhteobdf:";
int32_t opt;
int32_t tracer;
int32_t do_stderr = QB_FALSE;
+ int32_t do_stdout = QB_FALSE;
int32_t do_dump_blackbox = QB_FALSE;
char *logfile = NULL;
int32_t log_fd = -1;
@@ -150,6 +151,9 @@ int32_t main(int32_t argc, char *argv[])
case 'e':
do_stderr = QB_TRUE;
break;
+ case 'o':
+ do_stdout = QB_TRUE;
+ break;
case 'b':
do_blackbox = QB_TRUE;
break;
@@ -178,19 +182,26 @@ int32_t main(int32_t argc, char *argv[])
qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_THREADED, do_threaded);
qb_log_tags_stringify_fn_set(my_tags_stringify);
- tracer = qb_log_custom_open(trace_logger, NULL, NULL, NULL);
if (do_stderr) {
qb_log_filter_fn_set(m_filter);
qb_log_format_set(QB_LOG_STDERR, "[%p] %4g: %f:%l %b");
qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_ENABLED, QB_TRUE);
+ tracer = qb_log_custom_open(trace_logger, NULL, NULL, NULL);
qb_log_ctl(tracer, QB_LOG_CONF_ENABLED, QB_TRUE);
qb_log_format_set(tracer, "%4g: %n() %b");
qb_log_filter_ctl2(tracer, QB_LOG_FILTER_ADD,
QB_LOG_FILTER_FILE, __FILE__,
LOG_TRACE, 200);
}
+ if (do_stdout) {
+ qb_log_filter_ctl2(QB_LOG_STDOUT, QB_LOG_FILTER_ADD,
+ QB_LOG_FILTER_FILE, __FILE__,
+ LOG_ALERT, QB_MIN(LOG_DEBUG, _log_priority));
+ qb_log_format_set(QB_LOG_STDOUT, "[%p] %4g: %f:%l %b");
+ qb_log_ctl(QB_LOG_STDOUT, QB_LOG_CONF_ENABLED, QB_TRUE);
+ }
if (do_blackbox) {
qb_log_filter_ctl(QB_LOG_BLACKBOX, QB_LOG_FILTER_ADD,
QB_LOG_FILTER_FILE, "*", LOG_DEBUG);
diff --git a/include/qb/qblog.h b/include/qb/qblog.h
index 29cd148..7a8c66d 100644
--- a/include/qb/qblog.h
+++ b/include/qb/qblog.h
@@ -353,6 +353,7 @@ void qb_log_from_external_source_va(const char *function,
#define QB_LOG_SYSLOG 0
#define QB_LOG_STDERR 1
#define QB_LOG_BLACKBOX 2
+#define QB_LOG_STDOUT 3
#define QB_LOG_TARGET_MAX 32
diff --git a/lib/log.c b/lib/log.c
index 7fac41f..8879cfd 100644
--- a/lib/log.c
+++ b/lib/log.c
@@ -720,6 +720,7 @@ qb_log_init(const char *name, int32_t facility, uint8_t priority)
conf[QB_LOG_STDERR].state = QB_LOG_STATE_DISABLED;
conf[QB_LOG_BLACKBOX].state = QB_LOG_STATE_DISABLED;
+ conf[QB_LOG_STDOUT].state = QB_LOG_STATE_DISABLED;
logger_inited = QB_TRUE;
(void)qb_log_syslog_open(&conf[QB_LOG_SYSLOG]);
@@ -881,7 +882,8 @@ _log_target_enable(struct qb_log_target *t)
if (t->state == QB_LOG_STATE_ENABLED) {
return 0;
}
- if (t->pos == QB_LOG_STDERR) {
+ if (t->pos == QB_LOG_STDERR ||
+ t->pos == QB_LOG_STDOUT) {
rc = qb_log_stderr_open(t);
} else if (t->pos == QB_LOG_SYSLOG) {
rc = qb_log_syslog_open(t);
diff --git a/lib/log_file.c b/lib/log_file.c
index 7a77d8d..152c2fd 100644
--- a/lib/log_file.c
+++ b/lib/log_file.c
@@ -67,8 +67,13 @@ qb_log_stderr_open(struct qb_log_target *t)
t->logger = _file_logger;
t->reload = NULL;
t->close = NULL;
- (void)strlcpy(t->filename, "stderr", PATH_MAX);
- t->instance = stderr;
+ if (t->pos == QB_LOG_STDERR) {
+ (void)strlcpy(t->filename, "stderr", PATH_MAX);
+ t->instance = stderr;
+ } else {
+ (void)strlcpy(t->filename, "stdout", PATH_MAX);
+ t->instance = stdout;
+ }
return 0;
}
--
1.7.7.6
12 years, 1 month
question re feature
by Steven Dake
Hi,
I am developing an app which uses libqb's loop feature. I'd like to
know the maximum elapsed time in nanoseconds a job/timer/poller takes to
make sure my app (cape-ssh at http://pacemaker-cloud.org) is really
non-blocking.
A build-time option would be good (don't want to slow down the rest of
the users that don't use the feature with getting the system time).
Another option is to add a new api that takes a loop and specifies a
callback function to be called (containing as a parameter the elapsed
time, and for extra credit the offending function name) when a new high
water mark is set on nanosecond consumption and only executing the timer
calculations when the api is used.
Another option is a test patch which I could use for this purpose, but
not merge into the mainline.
thanks!
-steve
12 years, 1 month
[PATCH] LOOP: add a function to delete jobs
by Angus Salkeld
Signed-off-by: Angus Salkeld <asalkeld(a)redhat.com>
---
include/qb/qbloop.h | 20 ++++++++++++++++++++
lib/loop_job.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
lib/loop_poll.c | 2 +-
tests/check_loop.c | 44 +++++++++++++++++++++++++++++++++++++++++++-
4 files changed, 112 insertions(+), 2 deletions(-)
diff --git a/include/qb/qbloop.h b/include/qb/qbloop.h
index b2afecc..e482e29 100644
--- a/include/qb/qbloop.h
+++ b/include/qb/qbloop.h
@@ -107,6 +107,26 @@ int32_t qb_loop_job_add(qb_loop_t *l,
void *data,
qb_loop_job_dispatch_fn dispatch_fn);
+
+/**
+ * Delete a job from the mainloop.
+ *
+ * This will try to delete the job if it hasn't run yet.
+ *
+ * @note this will remove the first job that matches the
+ * paramaters (priority, data, dispatch_fn).
+ *
+ * @param l pointer to the loop instance
+ * @param p the priority
+ * @param data user data passed into the dispatch function
+ * @param dispatch_fn callback function
+ * @return status (0 == ok, -errno == failure)
+ */
+int32_t qb_loop_job_del(struct qb_loop *lp,
+ enum qb_loop_priority p,
+ void *data,
+ qb_loop_job_dispatch_fn dispatch_fn);
+
/**
* Add a timer to the mainloop.
* @note it is a one-shot job.
diff --git a/lib/loop_job.c b/lib/loop_job.c
index 3f261f2..23b3eb6 100644
--- a/lib/loop_job.c
+++ b/lib/loop_job.c
@@ -24,6 +24,7 @@
#include <qb/qblist.h>
#include <qb/qbloop.h>
#include "loop_int.h"
+#include "util_int.h"
struct qb_loop_job {
struct qb_loop_item item;
@@ -118,3 +119,50 @@ qb_loop_job_add(struct qb_loop *lp,
return 0;
}
+
+int32_t
+qb_loop_job_del(struct qb_loop *lp,
+ enum qb_loop_priority p,
+ void *data, qb_loop_job_dispatch_fn dispatch_fn)
+{
+ struct qb_loop_job *job;
+ struct qb_loop_item *item;
+ struct qb_loop *l = lp;
+
+ if (l == NULL) {
+ l = qb_loop_default_get();
+ }
+ if (l == NULL || dispatch_fn == NULL) {
+ return -EINVAL;
+ }
+ if (p > QB_LOOP_HIGH) {
+ return -EINVAL;
+ }
+
+ qb_list_for_each_entry(item, &l->level[p].wait_head, list) {
+ job = (struct qb_loop_job *)item;
+ if (job->dispatch_fn == dispatch_fn &&
+ job->item.user_data == data &&
+ job->item.type == QB_LOOP_JOB) {
+ qb_list_del(&job->item.list);
+ free(job);
+ return 0;
+ }
+ }
+
+ qb_list_for_each_entry(item, &l->level[p].job_head, list) {
+
+ if (item->type != QB_LOOP_JOB) {
+ continue;
+ }
+ job = (struct qb_loop_job *)item;
+ if (job->dispatch_fn == dispatch_fn &&
+ job->item.user_data == data) {
+ qb_loop_level_item_del(&l->level[p], item);
+ qb_util_log(LOG_DEBUG, "deleting job in JOBLIST");
+ return 0;
+ }
+ }
+
+ return -ENOENT;
+}
diff --git a/lib/loop_poll.c b/lib/loop_poll.c
index e379ebf..2f6fc20 100644
--- a/lib/loop_poll.c
+++ b/lib/loop_poll.c
@@ -819,7 +819,7 @@ qb_loop_timer_del(struct qb_loop * lp, qb_loop_timer_handle th)
}
if (pe->state == QB_POLL_ENTRY_JOBLIST) {
qb_loop_level_item_del(&l->level[pe->p], &pe->item);
- qb_util_log(LOG_DEBUG, "trying to delete timer in JOBLIST");
+ qb_util_log(LOG_DEBUG, "deleting timer in JOBLIST");
}
if (pe->state != QB_POLL_ENTRY_ACTIVE &&
pe->state != QB_POLL_ENTRY_JOBLIST) {
diff --git a/tests/check_loop.c b/tests/check_loop.c
index 3090faf..8bd862c 100644
--- a/tests/check_loop.c
+++ b/tests/check_loop.c
@@ -221,6 +221,44 @@ START_TEST(test_job_rate_limit)
}
END_TEST
+static void job_stop_and_del_1(void *data)
+{
+ int32_t res;
+ qb_loop_t *l = (qb_loop_t *)data;
+ job_3_run_count++;
+ res = qb_loop_job_del(l, QB_LOOP_MED, l, job_1);
+ ck_assert_int_eq(res, 0);
+ qb_loop_stop(l);
+}
+
+START_TEST(test_job_add_del)
+{
+ int32_t res;
+ qb_loop_t *l = qb_loop_create();
+ fail_if(l == NULL);
+
+ res = qb_loop_job_add(l, QB_LOOP_MED, l, job_1);
+ ck_assert_int_eq(res, 0);
+ res = qb_loop_job_del(l, QB_LOOP_MED, l, job_1);
+ ck_assert_int_eq(res, 0);
+
+ job_1_run_count = 0;
+ job_3_run_count = 0;
+
+ res = qb_loop_job_add(l, QB_LOOP_MED, l, job_1);
+ ck_assert_int_eq(res, 0);
+ res = qb_loop_job_add(l, QB_LOOP_HIGH, l, job_stop_and_del_1);
+ ck_assert_int_eq(res, 0);
+
+ qb_loop_run(l);
+ ck_assert_int_eq(job_1_run_count, 0);
+ ck_assert_int_eq(job_3_run_count, 1);
+
+ qb_loop_destroy(l);
+}
+END_TEST
+
+
static Suite *loop_job_suite(void)
{
TCase *tc;
@@ -248,6 +286,10 @@ static Suite *loop_job_suite(void)
tcase_set_timeout(tc, 5);
suite_add_tcase(s, tc);
+ tc = tcase_create("add_del");
+ tcase_add_test(tc, test_job_add_del);
+ suite_add_tcase(s, tc);
+
return s;
}
@@ -553,7 +595,7 @@ int32_t main(void)
qb_log_init("check", LOG_USER, LOG_EMERG);
qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_FALSE);
qb_log_filter_ctl(QB_LOG_STDERR, QB_LOG_FILTER_ADD,
- QB_LOG_FILTER_FILE, "*", LOG_INFO);
+ QB_LOG_FILTER_FILE, "*", LOG_DEBUG);
qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_ENABLED, QB_TRUE);
srunner_run_all(sr, CK_VERBOSE);
--
1.7.7.6
12 years, 1 month
[PATCH 1/3] LOG: Add qb_log_filter_fn_set()
by Angus Salkeld
Signed-off-by: Angus Salkeld <asalkeld(a)redhat.com>
---
examples/simplelog.c | 25 +++++++++++++++++------
include/qb/qblog.h | 24 +++++++++++++++++++++++
lib/log.c | 42 +++++++++++++++++++++++++++++++++++++++-
tests/check_log.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 133 insertions(+), 9 deletions(-)
diff --git a/examples/simplelog.c b/examples/simplelog.c
index 593dd5c..c0607c2 100644
--- a/examples/simplelog.c
+++ b/examples/simplelog.c
@@ -29,6 +29,8 @@
#define MY_TAG_TWO (1 << 1)
#define MY_TAG_THREE (1 << 2)
+static int32_t _log_priority = LOG_WARNING;
+
static void func_one(void)
{
FILE* fd;
@@ -115,12 +117,23 @@ trace_logger(int32_t t,
fprintf(stderr, "%s\n", output_buffer);
}
+static void
+m_filter(struct qb_log_callsite *cs)
+{
+ if ((cs->priority >= LOG_ALERT &&
+ cs->priority <= _log_priority) &&
+ strcmp(cs->filename, __FILE__) == 0) {
+ qb_bit_set(cs->targets, QB_LOG_STDERR);
+ } else {
+ qb_bit_clear(cs->targets, QB_LOG_STDERR);
+ }
+}
+
int32_t main(int32_t argc, char *argv[])
{
const char *options = "vhtebdf:";
int32_t opt;
int32_t tracer;
- int32_t priority = LOG_WARNING;
int32_t do_stderr = QB_FALSE;
int32_t do_dump_blackbox = QB_FALSE;
char *logfile = NULL;
@@ -144,7 +157,7 @@ int32_t main(int32_t argc, char *argv[])
logfile = optarg;
break;
case 'v':
- priority++;
+ _log_priority++;
break;
case 'h':
default:
@@ -168,10 +181,8 @@ int32_t main(int32_t argc, char *argv[])
tracer = qb_log_custom_open(trace_logger, NULL, NULL, NULL);
if (do_stderr) {
- qb_log_filter_ctl2(QB_LOG_STDERR, QB_LOG_FILTER_ADD,
- QB_LOG_FILTER_FILE, __FILE__,
- LOG_ALERT, QB_MIN(LOG_DEBUG, priority));
- qb_log_format_set(QB_LOG_STDERR, "%4g: %f:%l [%p] %b");
+ qb_log_filter_fn_set(m_filter);
+ qb_log_format_set(QB_LOG_STDERR, "[%p] %4g: %f:%l %b");
qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_ENABLED, QB_TRUE);
qb_log_ctl(tracer, QB_LOG_CONF_ENABLED, QB_TRUE);
@@ -190,7 +201,7 @@ int32_t main(int32_t argc, char *argv[])
if (logfile) {
log_fd = qb_log_file_open(logfile);
qb_log_filter_ctl(log_fd, QB_LOG_FILTER_ADD,
- QB_LOG_FILTER_FILE, __FILE__, priority);
+ QB_LOG_FILTER_FILE, __FILE__, _log_priority);
qb_log_format_set(log_fd, "[%N] %t %n() [%p] %b");
qb_log_ctl(log_fd, QB_LOG_CONF_THREADED, do_threaded);
qb_log_ctl(log_fd, QB_LOG_CONF_ENABLED, QB_TRUE);
diff --git a/include/qb/qblog.h b/include/qb/qblog.h
index f1a6305..3d7bf82 100644
--- a/include/qb/qblog.h
+++ b/include/qb/qblog.h
@@ -237,6 +237,8 @@ struct qb_log_callsite {
uint32_t tags;
} __attribute__((aligned(8)));
+typedef void (*qb_log_filter_fn)(struct qb_log_callsite * cs);
+
/* will be assigned by ld linker magic */
#ifdef QB_HAVE_ATTRIBUTE_SECTION
extern struct qb_log_callsite __start___verbose[];
@@ -462,6 +464,28 @@ int32_t qb_log_filter_ctl2(int32_t value, enum qb_log_filter_conf c,
enum qb_log_filter_type type, const char * text,
uint8_t high_priority, uint8_t low_priority);
+
+/**
+ * Instead of using the qb_log_filter_ctl() functions you
+ * can apply the filters manually by defining a callback
+ * and setting the targets field using qb_bit_set() and
+ * qb_bit_clear() like the following below.
+ * @code
+ * static void
+ * m_filter(struct qb_log_callsite *cs)
+ * {
+ * if ((cs->priority >= LOG_ALERT &&
+ * cs->priority <= LOG_DEBUG) &&
+ * strcmp(cs->filename, "my_c_file.c") == 0) {
+ * qb_bit_set(cs->targets, QB_LOG_SYSLOG);
+ * } else {
+ * qb_bit_clear(cs->targets, QB_LOG_SYSLOG);
+ * }
+ * }
+ * @endcode
+ */
+int32_t qb_log_filter_fn_set(qb_log_filter_fn fn);
+
/**
* Set the callback to map the 'tags' bit map to a string.
*/
diff --git a/lib/log.c b/lib/log.c
index 867334f..0785b21 100644
--- a/lib/log.c
+++ b/lib/log.c
@@ -43,6 +43,7 @@ static uint32_t conf_active_max = 0;
static int32_t in_logger = QB_FALSE;
static int32_t logger_inited = QB_FALSE;
static pthread_rwlock_t _listlock;
+static qb_log_filter_fn _custom_filter_fn = NULL;
static QB_LIST_DECLARE(tags_head);
static QB_LIST_DECLARE(callsite_sections);
@@ -268,7 +269,7 @@ qb_log_from_external_source_va(const char *function,
flt = qb_list_entry(f_item, struct qb_log_filter, list);
_log_filter_apply_to_cs(cs, t->pos, flt->conf, flt->type,
flt->text, flt->high_priority,
- flt->low_priority);
+ flt->low_priority);
}
}
if (tags == 0) {
@@ -276,11 +277,14 @@ qb_log_from_external_source_va(const char *function,
flt = qb_list_entry(f_item, struct qb_log_filter, list);
_log_filter_apply_to_cs(cs, flt->new_value, flt->conf, flt->type,
flt->text, flt->high_priority,
- flt->low_priority);
+ flt->low_priority);
}
} else {
cs->tags = tags;
}
+ if (_custom_filter_fn) {
+ _custom_filter_fn(cs);
+ }
pthread_rwlock_unlock(&_listlock);
}
qb_log_real_va_(cs, ap);
@@ -306,6 +310,7 @@ qb_log_callsites_register(struct qb_log_callsite *_start,
struct qb_log_callsite *_stop)
{
struct callsite_section *sect;
+ struct qb_log_callsite *cs;
struct qb_log_target *t;
struct qb_log_filter *flt;
int32_t pos;
@@ -354,6 +359,14 @@ qb_log_callsites_register(struct qb_log_callsite *_start,
flt->high_priority, flt->low_priority);
}
pthread_rwlock_unlock(&_listlock);
+ if (_custom_filter_fn) {
+ for (cs = sect->start; cs < sect->stop; cs++) {
+ if (cs->lineno == 0) {
+ break;
+ }
+ _custom_filter_fn(cs);
+ }
+ }
return 0;
}
@@ -588,6 +601,31 @@ qb_log_filter_ctl2(int32_t t, enum qb_log_filter_conf c,
}
int32_t
+qb_log_filter_fn_set(qb_log_filter_fn fn)
+{
+ struct callsite_section *sect;
+ struct qb_log_callsite *cs;
+
+ if (!logger_inited) {
+ return -EINVAL;
+ }
+ _custom_filter_fn = fn;
+ if (_custom_filter_fn == NULL) {
+ return 0;
+ }
+
+ qb_list_for_each_entry(sect, &callsite_sections, list) {
+ for (cs = sect->start; cs < sect->stop; cs++) {
+ if (cs->lineno == 0) {
+ break;
+ }
+ _custom_filter_fn(cs);
+ }
+ }
+ return 0;
+}
+
+int32_t
qb_log_filter_ctl(int32_t t, enum qb_log_filter_conf c,
enum qb_log_filter_type type,
const char *text, uint8_t priority)
diff --git a/tests/check_log.c b/tests/check_log.c
index 19f84f1..318de9a 100644
--- a/tests/check_log.c
+++ b/tests/check_log.c
@@ -186,6 +186,53 @@ static void log_it_please(void)
qb_leave();
}
+
+static int32_t _cust_t = -1;
+static void
+m_filter(struct qb_log_callsite *cs)
+{
+ if ((cs->priority >= LOG_ALERT &&
+ cs->priority <= LOG_INFO) ||
+ cs->tags > 0) {
+ qb_bit_set(cs->targets, _cust_t);
+ } else {
+ qb_bit_clear(cs->targets, _cust_t);
+ }
+}
+
+
+START_TEST(test_log_filter_fn)
+{
+ int32_t rc;
+
+ qb_log_init("test", LOG_USER, LOG_EMERG);
+ qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_FALSE);
+
+ _cust_t = qb_log_custom_open(_test_logger, NULL, NULL, NULL);
+ _ck_assert_int(_cust_t, >, QB_LOG_BLACKBOX);
+ rc = qb_log_ctl(_cust_t, QB_LOG_CONF_ENABLED, QB_TRUE);
+ ck_assert_int_eq(rc, 0);
+
+ /*
+ * test the custom filter function.
+ * make sure qb_log, and qb_log_from_external_source are filtered.
+ */
+ qb_log_filter_fn_set(m_filter);
+ num_msgs = 0;
+
+ qb_log(LOG_NOTICE, "qb_log_filter_fn_set good");
+ qb_log_from_external_source(__func__, __FILE__, "%s", LOG_INFO,
+ __LINE__, 0, "qb_log_filter_fn_set good");
+ qb_log(LOG_TRACE, "qb_log_filter_fn_set bad");
+ qb_log_from_external_source(__func__, __FILE__, "%s", LOG_DEBUG,
+ __LINE__, 44, "qb_log_filter_fn_set woot");
+ qb_log_from_external_source(__func__, __FILE__, "%s", LOG_DEBUG,
+ __LINE__, 0, "qb_log_filter_fn_set bad");
+
+ ck_assert_int_eq(num_msgs, 3);
+}
+END_TEST
+
START_TEST(test_log_basic)
{
int32_t t;
@@ -533,6 +580,10 @@ static Suite *log_suite(void)
tcase_add_test(tc, test_log_long_msg);
suite_add_tcase(s, tc);
+ tc = tcase_create("filter_ft");
+ tcase_add_test(tc, test_log_filter_fn);
+ suite_add_tcase(s, tc);
+
return s;
}
--
1.7.7.6
12 years, 1 month
howto filter libqb logs
by Dietmar Maurer
Is it possible to remove informational log messages form libqb. I now get:
... [libqb] info: IPC credentials authenticated
I am only interested in critical errors from libqb (pri < LOG_WARNING).
But I want to log informational messages from my application (LOG_INFO).
- Dietmar
12 years, 1 month