On 26/12/11 15:36 -0700, Steven Dake wrote:
This API works by allowing the API user to keep a list of samples internally.
Nice idea.
Every time a new sample is taken, the difference between the current sample and the first sample in the window is returned. When the sample array is filled, old entries drop off the sample list.
The use case where this is helpful is recovery escalation. Every time a failure occurs we take a sample. If the resulting window is less then the escalation window, an escalation should occur and the sample window should be reset.
Is it not worth seperating the sampling (writing a new sample) and reading the sample?
This seems to be a logical extension of the stopwatch (but with splits). The problem with the current API is you can't go back and re-read the split times (write only API).
What you think?
-A
Signed-off-by: Steven Dake sdake@redhat.com
include/qb/qbutil.h | 25 +++++++++++++ lib/util.c | 64 ++++++++++++++++++++++++++++++++ tests/Makefile.am | 8 +++- tests/check_util.c | 100 +++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 195 insertions(+), 2 deletions(-) create mode 100644 tests/check_util.c
diff --git a/include/qb/qbutil.h b/include/qb/qbutil.h index 2b450e9..d737ec2 100644 --- a/include/qb/qbutil.h +++ b/include/qb/qbutil.h @@ -171,6 +171,31 @@ uint64_t qb_util_stopwatch_us_elapsed_get(qb_util_stopwatch_t *sw); */ float qb_util_stopwatch_sec_elapsed_get(qb_util_stopwatch_t *sw);
+typedef struct qb_util_samplewindow qb_util_samplewindow_t;
+/**
- Create a timer sample window
- */
+qb_util_samplewindow_t * qb_util_samplewindow_create(uint32_t size);
+/**
- Free a timer sample window
- */
+void qb_util_samplewindow_free(qb_util_samplewindow_t *sw);
+/**
- Get the elapsed time in micro seconds across the sample window.
- A return value of 0 indicates there have not been enough samples
- to determine the elapsed time.
- */
+uint64_t qb_util_samplewindow_sample(qb_util_samplewindow_t *sw);
+/*
- Reset the sample window
- */
+void qb_util_samplewindow_reset(qb_util_samplewindow_t *sw);
/* *INDENT-OFF* */ #ifdef __cplusplus } diff --git a/lib/util.c b/lib/util.c index 51c94bb..d9f11c6 100644 --- a/lib/util.c +++ b/lib/util.c @@ -272,3 +272,67 @@ qb_util_stopwatch_sec_elapsed_get(qb_util_stopwatch_t * sw) return ((float)e6 / (float)QB_TIME_US_IN_SEC); }
+struct qb_util_samplewindow {
- uint32_t size;
- uint32_t entries;
- uint64_t *entry_list;
+};
+/**
- Create a timer sample window
- */
+qb_util_samplewindow_t * qb_util_samplewindow_create(uint32_t size) +{
- struct qb_util_samplewindow *sw;
- sw = (struct qb_util_samplewindow *)calloc(1, sizeof(struct qb_util_stopwatch));
- sw->size = size;
- sw->entry_list = (uint64_t *)calloc(1, sizeof (uint64_t) * size);
- if (sw->entry_list == NULL) {
free (sw);
sw = NULL;
- }
- return sw;
+}
+/**
- Free a timer sample window
- */
+void qb_util_samplewindow_free(qb_util_samplewindow_t *sw) +{
- free(sw->entry_list);
- free(sw);
+}
+/**
- Get the elapsed time in micro seconds across the sample window.
- A return value of 0 indicates there have not been enough samples
- to determine the elapsed time.
- */
+uint64_t qb_util_samplewindow_sample(qb_util_samplewindow_t *sw) +{
- uint32_t new_entry_pos;
- uint64_t time_start;
- uint64_t time_end;
- new_entry_pos = sw->entries % (sw->size);
- sw->entry_list[new_entry_pos] = qb_util_nano_current_get();
- sw->entries++;
- if (sw->entries < sw->size) {
return 0ULL;
- }
- time_start = sw->entry_list[(new_entry_pos) % sw->size];
- time_end = sw->entry_list[(new_entry_pos + 1) % sw->size];
- return (time_start - time_end) / QB_TIME_NS_IN_USEC;
+}
+/*
- Reset the sample window
- */
+void qb_util_samplewindow_reset(qb_util_samplewindow_t *sw) +{
- sw->entries = 0;
+} diff --git a/tests/Makefile.am b/tests/Makefile.am index d8f64e2..dd73363 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -73,11 +73,11 @@ bench_log_LDADD = $(LIB_RT) $(top_builddir)/lib/libqb.la if HAVE_CHECK EXTRA_DIST += resources.test
-TESTS = array.test map.test rb.test log.test loop.test ipc.test resources.test +TESTS = array.test map.test rb.test log.test loop.test ipc.test resources.test util.test
resources.log: rb.log log.log ipc.log
-check_PROGRAMS = array.test map.test rb.test log.test loop.test ipc.test +check_PROGRAMS = array.test map.test rb.test log.test loop.test ipc.test util.test check_SCRIPTS = resources.test
array_test_SOURCES = check_array.c $(top_builddir)/include/qb/qbarray.h @@ -104,6 +104,10 @@ log_test_SOURCES = check_log.c $(top_builddir)/include/qb/qblog.h log_test_CFLAGS = @CHECK_CFLAGS@ -I$(top_srcdir)/include log_test_LDADD = $(top_builddir)/lib/libqb.la $(LIB_RT) @CHECK_LIBS@
+util_test_SOURCES = check_util.c $(top_builddir)/include/qb/qbutil.h +util_test_CFLAGS = @CHECK_CFLAGS@ -I$(top_srcdir)/include +util_test_LDADD = $(top_builddir)/lib/libqb.la $(LIB_RT) @CHECK_LIBS@
endif
clean-generic: diff --git a/tests/check_util.c b/tests/check_util.c new file mode 100644 index 0000000..0313325 --- /dev/null +++ b/tests/check_util.c @@ -0,0 +1,100 @@ +/*
- Copyright (c) 2010 Red Hat, Inc.
- All rights reserved.
- Author: Steven Dake sdake@redhat.com
- This file is part of libqb.
- libqb is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation, either version 2.1 of the License, or
- (at your option) any later version.
- libqb is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
- You should have received a copy of the GNU Lesser General Public License
- along with libqb. If not, see http://www.gnu.org/licenses/.
- */
+#include "os_base.h" +#include <check.h>
+#include <qb/qbdefs.h> +#include <qb/qbutil.h> +#include <qb/qblog.h>
+START_TEST(test_check_samplewindow) +{
- qb_util_samplewindow_t *sw;
- uint64_t res;
- sw = qb_util_samplewindow_create(5);
- res = qb_util_samplewindow_sample(sw);
- ck_assert_int_eq(res, 0ULL);
- usleep(10000);
- res = qb_util_samplewindow_sample(sw);
- ck_assert_int_eq(res, 0ULL);
- usleep(20000);
- res = qb_util_samplewindow_sample(sw);
- ck_assert_int_eq(res, 0ULL);
- usleep(30000);
- res = qb_util_samplewindow_sample(sw);
- ck_assert_int_eq(res, 0ULL);
- usleep(40000);
- res = qb_util_samplewindow_sample(sw);
- /*
* window should be 100000 (40000 + 30000 + 20000 + 10000) usec
*/
- ck_assert(res > 95000);
- ck_assert(res < 105000);
- usleep(50000);
- res = qb_util_samplewindow_sample(sw);
- /*
* window should be 140000 (50000 + 40000 + 30000 + 20000) usec
*/
- ck_assert(res > 135000);
- ck_assert(res < 145000);
+} +END_TEST
+static Suite *util_suite(void) +{
- TCase *tc;
- Suite *s = suite_create("qb_util");
- tc = tcase_create("properop");
- tcase_add_test(tc, test_check_samplewindow);
- suite_add_tcase(s, tc);
- return s;
+}
+int32_t main(void) +{
- int32_t number_failed;
- Suite *s = util_suite();
- SRunner *sr = srunner_create(s);
- 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_ctl(QB_LOG_STDERR, QB_LOG_CONF_ENABLED, QB_TRUE);
- srunner_run_all(sr, CK_VERBOSE);
- number_failed = srunner_ntests_failed(sr);
- srunner_free(sr);
- return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
+}
1.7.7.4
quarterback-devel mailing list quarterback-devel@lists.fedorahosted.org https://fedorahosted.org/mailman/listinfo/quarterback-devel