summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordufour2010-02-12 15:51:33 +0000
committerdufour2010-02-12 15:51:33 +0000
commit3443de8db5c34138ae29a5ad7635ae5acb774143 (patch)
tree5adcd8decb5b7e09f7f3d81b2561e59c4a081d80
parentc448b9ca2214caeb0023754bb532e09987daec77 (diff)
cesar/lib/stats: extend stats to support access mode, closes #1239
There are now three kinds of statistics: - one accessible in read only (statistics), - another one accessible in write only, - others accessible in read and write (configurations). Callback have now a defined type. git-svn-id: svn+ssh://pessac/svn/cesar/trunk@6714 017c9cb6-072f-447c-8318-d5b54f68fe89
-rw-r--r--cesar/cp/msg/test/src/msg_vs.c12
-rw-r--r--cesar/lib/src/stats.c352
-rw-r--r--cesar/lib/stats.h93
-rw-r--r--cesar/lib/test/stats/src/test_stats.c335
-rw-r--r--cesar/mac/sar/src/sar.c9
-rw-r--r--cesar/test_general/station/common/src/station.c9
6 files changed, 663 insertions, 147 deletions
diff --git a/cesar/cp/msg/test/src/msg_vs.c b/cesar/cp/msg/test/src/msg_vs.c
index 028b6c43c9..f0143d45f1 100644
--- a/cesar/cp/msg/test/src/msg_vs.c
+++ b/cesar/cp/msg/test/src/msg_vs.c
@@ -1436,10 +1436,14 @@ test_case_msg_vs_get_stats (void)
u64 value_u64 = 0x1234567890ABCDEFULL;
lib_stats_init ();
- lib_stats_set_stat_value_notype ("value_u8", &value_u8);
- lib_stats_set_stat_value_notype ("value_u16", &value_u16);
- lib_stats_set_stat_value_notype ("value_u32", &value_u32);
- lib_stats_set_stat_value_notype ("value_u64", &value_u64);
+ lib_stats_set_stat_value_notype ("value_u8", &value_u8,
+ LIB_STATS_ACCESS_READ_ONLY);
+ lib_stats_set_stat_value_notype ("value_u16", &value_u16,
+ LIB_STATS_ACCESS_READ_ONLY);
+ lib_stats_set_stat_value_notype ("value_u32", &value_u32,
+ LIB_STATS_ACCESS_READ_ONLY);
+ lib_stats_set_stat_value_notype ("value_u64", &value_u64,
+ LIB_STATS_ACCESS_READ_ONLY);
/* Request an existing page number */
test_begin (test, "CM_VS_GET_STATS.CNF send with content")
diff --git a/cesar/lib/src/stats.c b/cesar/lib/src/stats.c
index 79d12da30e..f7d34e9cba 100644
--- a/cesar/lib/src/stats.c
+++ b/cesar/lib/src/stats.c
@@ -17,6 +17,8 @@
#include "slab.h"
#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
/***********************************************************/
/* Local Definitions */
@@ -29,7 +31,18 @@ typedef struct lib_stats_stat_t
const char *name;
lib_stats_types_t type;
void *value;
- void *(*callback) (void);
+ /**
+ * Callback in read access mode.
+ */
+ lib_stats_cb_r_t callback_read;
+ /**
+ * Callback in write access mode.
+ */
+ lib_stats_cb_w_t callback_write;
+ /**
+ * Access mode of statistics.
+ */
+ lib_stats_access_t mode;
struct lib_stats_stat_t *next_stat;
} lib_stats_stat_t;
@@ -83,19 +96,27 @@ quartet2ascii (u8 quartet)
/**
* Prepare the book to store a new stat
* \param name string to be displayed before the stat value
+ * \param mode access mode
* \param type type and max size of the value in octet
*/
void
-lib_stats_new_stat (const char *name, lib_stats_types_t type)
+lib_stats_new_stat (const char *name, lib_stats_access_t mode,
+ lib_stats_types_t type)
{
/* Check parameters */
dbg_assert (name);
+ dbg_assert (mode >= LIB_STATS_ACCESS_READ_ONLY
+ && mode <= LIB_STATS_ACCESS_READ_WRITE);
dbg_assert (type);
- int stat_size;
+ int stat_size = 0;
- /* String lenght for this stat */
- stat_size = strlen (name) + (2 * type) + 2;
+ if (mode != LIB_STATS_ACCESS_WRITE_ONLY)
+ {
+ /* Compute string size:
+ name + length on hexa + separation characters. */
+ stat_size = strlen (name) + (2 * type) + 2;
+ }
/* Check if new stat doesn't fit in the current page */
if ((lib_stats_book.last_page->page_size + stat_size)
@@ -133,12 +154,83 @@ lib_stats_new_stat (const char *name, lib_stats_types_t type)
/* Store stat's informations and update page*/
lib_stats_book.last_page->last_stat->name = name;
lib_stats_book.last_page->last_stat->type = type;
+ lib_stats_book.last_page->last_stat->mode = mode;
lib_stats_book.last_page->last_stat->next_stat = NULL;
lib_stats_book.last_page->nb_stats++;
lib_stats_book.last_page->page_size += stat_size;
}
+/**
+ * Write a value to a statistic.
+ * \param stat the statistic that should be written
+ * \param value the value to write to the statistic
+ * \return false if something goes wrong, true otherwise
+ */
+bool
+lib_stats_write_stat_ (lib_stats_stat_t *stat, const char *value)
+{
+ /* Check parameters. */
+ dbg_assert (stat);
+ dbg_assert (value);
+
+ /* Not writable? */
+ if (stat->mode == LIB_STATS_ACCESS_READ_ONLY)
+ return false;
+
+ /* If we read here, we can write the statistics: let's decode it. */
+ /* Decode value. */
+ char *endptr = NULL;
+ /* Clear errno. */
+ errno = 0;
+ /* Decode. */
+ u64 val = strtoull (value, &endptr, 0);
+ /* Error. */
+ if (errno || endptr == value)
+ return false;
+
+ /* Check value size. */
+ if (stat->type != LIB_STATS_8_BYTE)
+ {
+ u64 max = 1ull << (stat->type * 8);
+ if (val >= max)
+ {
+ return false;
+ }
+ }
+
+ if (stat->value == NULL)
+ {
+ dbg_assert (stat->callback_write);
+ /* Callback write. */
+ stat->callback_write (val);
+ }
+ else
+ {
+ /* Set new value. */
+ switch (stat->type)
+ {
+ case LIB_STATS_1_BYTE:
+ *((u8 *) stat->value) = val;
+ break;
+ case LIB_STATS_2_BYTE:
+ *((u16 *) stat->value) = val;
+ break;
+ case LIB_STATS_4_BYTE:
+ *((u32 *) stat->value) = val;
+ break;
+ case LIB_STATS_8_BYTE:
+ *((u64 *) stat->value) = val;
+ break;
+ default:
+ return false;
+ }
+ }
+
+ /* No error. */
+ return true;
+}
+
/***********************************************************/
/* Public Functions */
/*********************************************************/
@@ -216,106 +308,112 @@ lib_stats_get_page (bitstream_t *bitstream, u8 page)
while (target_stat)
{
- int nb_quartets = 2 * target_stat->type; /* nb quartets to send
- depends on type */
-
- /* Write value's name to bitstream */
- bitstream_write_buf (bitstream, (const u8 *) target_stat->name,
- strlen (target_stat->name));
- bitstream_write (bitstream, ':', 8);
-
- /* Get value depending on it's type */
- switch (target_stat->type)
+ /* Skip write only statistics. */
+ if (target_stat->mode != LIB_STATS_ACCESS_WRITE_ONLY)
{
- case LIB_STATS_1_BYTE:
+ /* nb quartets to send depends on type */
+ int nb_quartets = 2 * target_stat->type;
+ /* Write value's name to bitstream */
+ bitstream_write_buf (bitstream, (const u8 *)
+ target_stat->name, strlen
+ (target_stat->name));
+ bitstream_write (bitstream, ':', 8);
+
+ /* Get value depending on it's type */
+ switch (target_stat->type)
{
- u8 stat_value;
-
- if (target_stat->value)
- stat_value = *(u8 *) (target_stat->value);
- else
- stat_value = *(u8 *) (target_stat->callback ());
-
- /* Write value to bitstream starting with MSB */
- while (nb_quartets)
- bitstream_write (
- bitstream,
- quartet2ascii ((u8) (stat_value
- >> (--nb_quartets * 4))),
- 8);
+ case LIB_STATS_1_BYTE:
+ {
+ u8 stat_value;
+
+ if (target_stat->value)
+ stat_value = *(u8 *) (target_stat->value);
+ else
+ stat_value =
+ *(u8 *) (target_stat->callback_read ());
+
+ /* Write value to bitstream starting with MSB */
+ while (nb_quartets)
+ bitstream_write (
+ bitstream,
+ quartet2ascii ((u8) (stat_value
+ >> (--nb_quartets * 4))),
+ 8);
+ }
+ break;
+
+ case LIB_STATS_2_BYTE:
+ {
+ u16 stat_value;
+
+ if (target_stat->value)
+ stat_value = *(u16 *) (target_stat->value);
+ else
+ stat_value =
+ *(u16 *) (target_stat->callback_read ());
+
+ /* Write value to bitstream starting with MSB */
+ while (nb_quartets)
+ bitstream_write (
+ bitstream,
+ quartet2ascii ((u8) (stat_value
+ >> (--nb_quartets * 4))),
+ 8);
+ }
+ break;
+
+ case LIB_STATS_4_BYTE:
+ {
+ u32 stat_value;
+
+ if (target_stat->value)
+ stat_value = *(u32 *) (target_stat->value);
+ else
+ stat_value =
+ *(u32 *) (target_stat->callback_read ());
+
+ /* Write value to bitstream starting with MSB */
+ while (nb_quartets)
+ bitstream_write (
+ bitstream,
+ quartet2ascii ((u8) (stat_value
+ >> (--nb_quartets * 4))),
+ 8);
+ }
+ break;
+
+ case LIB_STATS_8_BYTE:
+ {
+ u64 stat_value;
+
+ if (target_stat->value)
+ stat_value = *(u64 *) (target_stat->value);
+ else
+ stat_value =
+ *(u64 *) (target_stat->callback_read ());
+
+ /* Write value to bitstream starting with MSB */
+ while (nb_quartets)
+ bitstream_write (
+ bitstream,
+ quartet2ascii ((u8) (stat_value
+ >> (--nb_quartets * 4))),
+ 8);
+ }
+ break;
+
+
+ default:
+ bitstream_write_buf (bitstream, (u8 *) "wrong_type",
+ strlen ("wrong_type"));
+ break;
}
- break;
-
- case LIB_STATS_2_BYTE:
- {
- u16 stat_value;
-
- if (target_stat->value)
- stat_value = *(u16 *) (target_stat->value);
- else
- stat_value = *(u16 *) (target_stat->callback ());
-
- /* Write value to bitstream starting with MSB */
- while (nb_quartets)
- bitstream_write (
- bitstream,
- quartet2ascii ((u8) (stat_value
- >> (--nb_quartets * 4))),
- 8);
- }
- break;
-
- case LIB_STATS_4_BYTE:
- {
- u32 stat_value;
-
- if (target_stat->value)
- stat_value = *(u32 *) (target_stat->value);
- else
- stat_value = *(u32 *) (target_stat->callback ());
-
- /* Write value to bitstream starting with MSB */
- while (nb_quartets)
- bitstream_write (
- bitstream,
- quartet2ascii ((u8) (stat_value
- >> (--nb_quartets * 4))),
- 8);
- }
- break;
-
- case LIB_STATS_8_BYTE:
- {
- u64 stat_value;
-
- if (target_stat->value)
- stat_value = *(u64 *) (target_stat->value);
- else
- stat_value = *(u64 *) (target_stat->callback ());
-
- /* Write value to bitstream starting with MSB */
- while (nb_quartets)
- bitstream_write (
- bitstream,
- quartet2ascii ((u8) (stat_value
- >> (--nb_quartets * 4))),
- 8);
- }
- break;
-
-
- default:
- bitstream_write_buf (bitstream, (u8 *) "wrong_type",
- strlen ("wrong_type"));
- break;
+ /* Inter-stat space if it's not the last one */
+ if (target_stat->next_stat)
+ bitstream_write (bitstream, ' ', 8);
}
-
/* Point to next stat */
target_stat = target_stat->next_stat;
-
- /* Inter-stat space if it's not the last one */
- if (target_stat)
- bitstream_write (bitstream, ' ', 8);
}
}
@@ -323,26 +421,70 @@ lib_stats_get_page (bitstream_t *bitstream, u8 page)
bitstream_write (bitstream, 0, 8);
}
+bool
+lib_stats_write_stat (const char *name, const char *value)
+{
+ /* Check parameter. */
+ dbg_assert (name);
+
+ /* Get first page. */
+ lib_stats_page_t *cur_page = lib_stats_book.first_page;
+
+ /* Go through all the pages of the book. */
+ while (cur_page)
+ {
+ /* Get first statistic. */
+ lib_stats_stat_t *cur_stat = cur_page->first_stat;
+ /* Go through all statistics of this page. */
+ while (cur_stat)
+ {
+ /* Is it the one? */
+ if (strcmp (cur_stat->name, name) == 0)
+ {
+ return lib_stats_write_stat_ (cur_stat, value);
+ }
+ /* Next statistic. */
+ cur_stat = cur_stat->next_stat;
+ }
+ /* Next page. */
+ cur_page = cur_page->next_page;
+ }
+
+ /* Not found. */
+ return false;
+}
+
void
lib_stats_set_stat_value (const char *name, void *value,
+ lib_stats_access_t mode,
lib_stats_types_t type)
{
dbg_assert (value);
- lib_stats_new_stat (name, type);
+ lib_stats_new_stat (name, mode, type);
lib_stats_book.last_page->last_stat->value = value;
- lib_stats_book.last_page->last_stat->callback = NULL;
+ lib_stats_book.last_page->last_stat->callback_read = NULL;
+ lib_stats_book.last_page->last_stat->callback_write = NULL;
}
void
-lib_stats_set_stat_callback (const char *name, void *(*callback) (void),
+lib_stats_set_stat_callback (const char *name, lib_stats_cb_r_t callback_read,
+ lib_stats_cb_w_t callback_write,
lib_stats_types_t type)
{
- dbg_assert (callback);
+ dbg_assert (callback_read || callback_write);
+
+ /* Guess access mode. */
+ lib_stats_access_t mode_r = 0, mode_w = 0;
+ if (callback_read)
+ mode_r = LIB_STATS_ACCESS_READ_ONLY;
+ if (callback_write)
+ mode_r = LIB_STATS_ACCESS_WRITE_ONLY;
- lib_stats_new_stat (name, type);
+ lib_stats_new_stat (name, mode_r | mode_w, type);
lib_stats_book.last_page->last_stat->value = NULL;
- lib_stats_book.last_page->last_stat->callback = callback;
+ lib_stats_book.last_page->last_stat->callback_read = callback_read;
+ lib_stats_book.last_page->last_stat->callback_write = callback_write;
}
diff --git a/cesar/lib/stats.h b/cesar/lib/stats.h
index 3a73c3c07e..2de3f8fd9f 100644
--- a/cesar/lib/stats.h
+++ b/cesar/lib/stats.h
@@ -12,8 +12,15 @@
* \brief Stats system.
* \ingroup lib
*
- * The stats module provide stats registering function and stats retrieving
- * function.
+ * The stats module provides access in read or write mode to different types
+ * of statistics (pointer to a value or callback). Basically, you can:
+ * - register in read/write mode statistics to add them to the book of
+ * statistics,
+ * - retrieve the whole list of statistics.
+ *
+ * Statistics are organized by page. Each page can contains the same amount of
+ * statistics contained in an MME (VS_GET_STATS). Pages does not include
+ * statistics in write only mode.
*/
#include "config/stats.h"
@@ -28,6 +35,37 @@ enum lib_stats_types_t
};
typedef enum lib_stats_types_t lib_stats_types_t;
+/**
+ * Access mode of the statistics.
+ */
+enum lib_stats_access_t
+{
+ /**
+ * Access in read mode only.
+ */
+ LIB_STATS_ACCESS_READ_ONLY = 1,
+ /**
+ * Access in write mode only.
+ */
+ LIB_STATS_ACCESS_WRITE_ONLY = 2,
+ /**
+ * Access in read/write mode.
+ */
+ LIB_STATS_ACCESS_READ_WRITE = 3,
+};
+typedef enum lib_stats_access_t lib_stats_access_t;
+
+/**
+ * Callback to read a statistic.
+ */
+typedef void *(*lib_stats_cb_r_t) (void);
+
+/**
+ * Callback to write to a statistic.
+ * \param val the new value
+ */
+typedef void (*lib_stats_cb_w_t) (u64 val);
+
BEGIN_DECLS
#if CONFIG_STATS
@@ -52,31 +90,64 @@ lib_stats_uninit (void);
* Write one page of stats to the bitstream.
* \param bitstream bitstream where to write the page
* \param page page number requested (starting from 0)
+ *
+ * Page does not include the statistics in write only mode.
*/
void
lib_stats_get_page (bitstream_t *bitstream, u8 page);
/**
+ * Write to a statistic.
+ * \param name name of the statistic to write
+ * \param value string corresponding to the value to write
+ * \return true if the statistics has been written, false otherwise
+ *
+ * This function is quite long (it goes through the whole book). If you have
+ * another way to directly access the statistic pointer, use it!
+ */
+bool
+lib_stats_write_stat (const char *name, const char *value);
+
+/**
* Add a new stat to the stat book using pointer to value.
* \param name string to be displayed before the stat value (no copy of the
* name is done)
* \param value pointer to the value of the stat
+ * \param mode access mode
* \param type type and max size of the value in octet
*/
void
lib_stats_set_stat_value (const char *name, void *value,
+ lib_stats_access_t mode,
lib_stats_types_t type);
/**
* Add a new stat to the stat book using callback.
* \param name string to be displayed before the stat value (no copy of the
* name is done)
- * \param callback if value param is NULL this callback will be used to
- * retrieve the stat
+ * \param callback_read callback to retrieve the statistics value (can be
+ * set to NULL if you do not want to enable read access)
+ * \param callback_write callback to write the statistics value (can be set
+ * to NULL if you do not want to enable write access)
* \param type type and max size of the value in octet
+ *
+ * callback_read should return a pointer to the type of this statistic. You
+ * must cast it when registering. For example:
+ * \code
+ * static u8 my_val = 0;
+ * u8 *
+ * cb_r (void)
+ * {
+ * return &my_val;
+ * }
+ * // ...
+ * lib_stats_set_stat_callback ("my_cb", (lib_stats_cb_r_t) cb_r, NULL,
+ * LIB_STATS_1_BYTE);
+ * \endcode
*/
void
-lib_stats_set_stat_callback (const char *name, void *(*callback) (void),
+lib_stats_set_stat_callback (const char *name, lib_stats_cb_r_t callback_read,
+ lib_stats_cb_w_t callback_write,
lib_stats_types_t type);
/**
@@ -84,22 +155,12 @@ lib_stats_set_stat_callback (const char *name, void *(*callback) (void),
* specifying its type.
* \param name string to be displayed before the stat value (no copy of the
* name is done)
+ * \param mode access mode
* \param value pointer to the value of the stat
*/
#define lib_stats_set_stat_value_notype(name, value, mode) \
lib_stats_set_stat_value ((name), (value), (mode), sizeof (*(value)))
-/**
- * Add a new stat to the stat book using callback without specifying its type.
- * \param name string to be displayed before the stat value (no copy of the
- * name is done)
- * \param callback if value param is NULL this callback will be used to
- * retrieve the stat
- */
-#define lib_stats_set_stat_callback_notype(name, callback) \
- lib_stats_set_stat_callback ((name), (void *) (callback), \
- sizeof (*(callback) ()))
-
#else /* !CONFIG_STATS */
#define lib_stats_init() ((void) 0)
diff --git a/cesar/lib/test/stats/src/test_stats.c b/cesar/lib/test/stats/src/test_stats.c
index bb88785577..69f08c49df 100644
--- a/cesar/lib/test/stats/src/test_stats.c
+++ b/cesar/lib/test/stats/src/test_stats.c
@@ -24,6 +24,14 @@
/***********************************************************/
/* Local Declarations */
/*********************************************************/
+
+struct my_type_t
+{
+ void *ptr;
+ u8 size;
+ char format[4];
+ void *w_ptr;
+};
u8 value_u8 = 0x12;
u16 value_u16 = 0x1234;
u32 value_u32 = 0x12345678;
@@ -53,6 +61,18 @@ callback_u64()
return &value_u64;
}
+#define MY_CALLBACK_W(type, val_name) \
+ void \
+ callback_w_ ## type (u64 (val_param)) \
+ { \
+ (val_name) = ((type) (val_param)); \
+ }
+
+MY_CALLBACK_W (u8, value_u8)
+MY_CALLBACK_W (u16, value_u16)
+MY_CALLBACK_W (u32, value_u32)
+MY_CALLBACK_W (u64, value_u64)
+
/***********************************************************/
/* Utils */
/*********************************************************/
@@ -118,14 +138,26 @@ stats_stat_update_test_case (test_t t)
value_u32 = 0x33333333;
value_u64 = 0x4444444455555555LL;
- lib_stats_set_stat_value_notype ("value_u8", &value_u8);
- lib_stats_set_stat_value_notype ("value_u16", &value_u16);
- lib_stats_set_stat_value_notype ("value_u32", &value_u32);
- lib_stats_set_stat_value_notype ("value_u64", &value_u64);
- lib_stats_set_stat_callback_notype ("callback_u8", callback_u8);
- lib_stats_set_stat_callback_notype ("callback_u16", callback_u16);
- lib_stats_set_stat_callback_notype ("callback_u32", callback_u32);
- lib_stats_set_stat_callback_notype ("callback_u64", callback_u64);
+ lib_stats_set_stat_value_notype ("value_u8", &value_u8,
+ LIB_STATS_ACCESS_READ_ONLY);
+ lib_stats_set_stat_value_notype ("value_u16", &value_u16,
+ LIB_STATS_ACCESS_READ_ONLY);
+ lib_stats_set_stat_value_notype ("value_u32", &value_u32,
+ LIB_STATS_ACCESS_READ_ONLY);
+ lib_stats_set_stat_value_notype ("value_u64", &value_u64,
+ LIB_STATS_ACCESS_READ_ONLY);
+ lib_stats_set_stat_callback ("callback_u8",
+ (lib_stats_cb_r_t) callback_u8, NULL,
+ sizeof (*(callback_u8) ()));
+ lib_stats_set_stat_callback ("callback_u16",
+ (lib_stats_cb_r_t) callback_u16, NULL,
+ sizeof (*(callback_u16) ()));
+ lib_stats_set_stat_callback ("callback_u32",
+ (lib_stats_cb_r_t) callback_u32, NULL,
+ sizeof (*(callback_u32) ()));
+ lib_stats_set_stat_callback ("callback_u64",
+ (lib_stats_cb_r_t) callback_u64, NULL,
+ sizeof (*(callback_u64) ()));
stats_read_page(buffer_test, 0);
stats_make_std_page(buffer_ref);
@@ -175,10 +207,14 @@ stats_page_update_test_case (test_t t)
test_begin (t, "Check that standard page is not complete nor empty")
{
- lib_stats_set_stat_value_notype ("value_u8", &value_u8);
- lib_stats_set_stat_value_notype ("value_u16", &value_u16);
- lib_stats_set_stat_value_notype ("value_u32", &value_u32);
- lib_stats_set_stat_value_notype ("value_u64", &value_u64);
+ lib_stats_set_stat_value_notype ("value_u8", &value_u8,
+ LIB_STATS_ACCESS_READ_ONLY);
+ lib_stats_set_stat_value_notype ("value_u16", &value_u16,
+ LIB_STATS_ACCESS_READ_ONLY);
+ lib_stats_set_stat_value_notype ("value_u32", &value_u32,
+ LIB_STATS_ACCESS_READ_ONLY);
+ lib_stats_set_stat_value_notype ("value_u64", &value_u64,
+ LIB_STATS_ACCESS_READ_ONLY);
stats_read_page(buffer_test, 0);
stats_make_std_page(buffer_ref);
@@ -191,10 +227,18 @@ stats_page_update_test_case (test_t t)
test_begin (t, "Check that standard page is complete")
{
- lib_stats_set_stat_callback_notype ("callback_u8", callback_u8);
- lib_stats_set_stat_callback_notype ("callback_u16", callback_u16);
- lib_stats_set_stat_callback_notype ("callback_u32", callback_u32);
- lib_stats_set_stat_callback_notype ("callback_u64", callback_u64);
+ lib_stats_set_stat_callback ("callback_u8",
+ (lib_stats_cb_r_t) callback_u8, NULL,
+ sizeof (*(callback_u8) ()));
+ lib_stats_set_stat_callback ("callback_u16",
+ (lib_stats_cb_r_t) callback_u16, NULL,
+ sizeof (*(callback_u16) ()));
+ lib_stats_set_stat_callback ("callback_u32",
+ (lib_stats_cb_r_t) callback_u32, NULL,
+ sizeof (*(callback_u32) ()));
+ lib_stats_set_stat_callback ("callback_u64",
+ (lib_stats_cb_r_t) callback_u64, NULL,
+ sizeof (*(callback_u64) ()));
stats_read_page(buffer_test, 0);
stats_make_std_page(buffer_ref);
@@ -222,7 +266,8 @@ stats_many_pages_test_case (test_t t)
{
sprintf(name[i], "val%3d", i);
values[i] = i;
- lib_stats_set_stat_value_notype (name[i], (values+i));
+ lib_stats_set_stat_value_notype (name[i], (values+i),
+ LIB_STATS_ACCESS_READ_ONLY);
}
stats_read_page(buffer_test, 1);
@@ -243,6 +288,254 @@ stats_many_pages_test_case (test_t t)
lib_stats_uninit ();
}
+static void
+stats_access_mode_test_case (test_t t)
+{
+ test_case_begin (t, "access mode");
+
+ test_begin (t, "no statistic in write only access mode when dumping page")
+ {
+ /* Initialize statistics module. */
+ lib_stats_init ();
+
+ uint i;
+ /* Maxim statistics to generate/tests. */
+ const uint max_stat = 500;
+ /* Maximum number of pages. */
+ const u8 max_page = 255;
+ /* To generate the name of statistic. */
+ char name[max_stat][10];
+ /* To generate the "name:value " for reference. */
+ char ref_name[40];
+ /* To store the format. */
+ char ref_format[20];
+ /* Reference book. */
+ char book_ref[max_page][ETH_PACKET_MAX_SIZE];
+ /* Position in the book. */
+ u8 cur_page = 0;
+ /* Position in the page. */
+ uint cur_pos = 1;
+ /* To ease different values usage. */
+ const struct my_type_t some_types[4] = {
+ { &value_u8, 1, "hh", NULL },
+ { &value_u16, 2, "h", NULL },
+ { &value_u32, 4, "l", NULL },
+ { &value_u64, 8, "ll", NULL },
+ };
+ char buffer_test[ETH_PACKET_MAX_SIZE];
+ /* Set some default values. */
+ value_u8 = 0x01;
+ value_u16 = 0x0123;
+ value_u32 = 0x01234567ul;
+ value_u64 = 0x0123456789ABCDEFull;
+
+ /* Add some statistics. */
+ for (i = 0; i < max_stat; i++)
+ {
+ /* Create name of the statistic. */
+ snprintf (name[i], COUNT (name[i]), "val_%04d", i);
+ /* Select an access mode. */
+ lib_stats_access_t mode = i % 3 + 1;
+ /* Fill reference buffer for statistics not write only. */
+ if (mode != LIB_STATS_ACCESS_WRITE_ONLY)
+ {
+ /* Generate format. */
+ snprintf (ref_format, COUNT (ref_format), "%%s:%%0%1d%sX ",
+ 2 * some_types[i % 4].size,
+ some_types[i % 4].format);
+ /* Create value. */
+ snprintf (ref_name, COUNT (ref_name), ref_format, name[i],
+ *((u64 *) some_types[i % 4].ptr));
+ /* Check it can fit on the current page. */
+ uint ref_len = strlen (ref_name);
+ dbg_assert (ref_len < 1024);
+ if (ref_len + cur_pos > 1024)
+ {
+ /* Next page. */
+ /* Remove last space. */
+ book_ref[cur_page][cur_pos - 1] = '\0';
+ dbg_assert (cur_page != 255);
+ cur_page++;
+ cur_pos = 1;
+ }
+ /* Copy name to the page. */
+ strcpy (&book_ref[cur_page][cur_pos], ref_name);
+ /* Increment counter of used space in the page. */
+ cur_pos += ref_len;
+ }
+ /* Add one of the possible statistics. */
+ lib_stats_set_stat_value (name[i],
+ some_types[i % 4].ptr,
+ mode,
+ some_types[i % 4].size);
+ }
+ /* Remove space on last page. */
+ book_ref[cur_page][cur_pos - 1] = '\0';
+
+ /* Check book is the same. */
+ for (i = 0; i < cur_page; i++)
+ {
+ /* Add page count in the first byte. */
+ book_ref[i][0] = cur_page + 1;
+ stats_read_page (buffer_test, i);
+ test_fail_if (strcmp (buffer_test, book_ref[i]) != 0);
+ }
+ lib_stats_uninit ();
+ } test_end;
+
+ test_begin (t, "write to a statistic")
+ {
+ /* Initialize statistics module. */
+ lib_stats_init ();
+
+ uint i, j;
+ /* Set some default values. */
+ value_u8 = 0x01;
+ value_u16 = 0x0123;
+ value_u32 = 0x01234567l;
+ value_u64 = 0x0123456789ABCDEFll;
+
+ char name[3 * 4][20];
+ char mode[3][20] = { "read", "write", "read_write" };
+ const struct my_type_t some_types[] = {
+ { &value_u8, 1, "v", NULL },
+ { &value_u16, 2, "v", NULL },
+ { &value_u32, 4, "v", NULL },
+ { &value_u64, 8, "v", NULL },
+ { &callback_u8, 1, "c", &callback_w_u8 },
+ { &callback_u16, 2, "c", &callback_w_u16 },
+ { &callback_u32, 4, "c", &callback_w_u32 },
+ { &callback_u64, 8, "c", &callback_w_u64 },
+ };
+
+ /* Add some statistics. */
+ for (i = 0; i < 3; i++)
+ {
+ for (j = 0; j < COUNT (some_types); j++)
+ {
+ u8 pos = i * COUNT (some_types) + j;
+ snprintf (name[pos], COUNT (name[pos]), "%s_%s_%1d",
+ mode[i], some_types[j].format, some_types[j].size);
+ if (some_types[j].format[0] == 'v')
+ lib_stats_set_stat_value (name[pos], some_types[j].ptr,
+ i + 1, some_types[j].size);
+ else
+ {
+ void *cr = NULL, *cw = NULL;
+ switch (i + 1)
+ {
+ case LIB_STATS_ACCESS_READ_ONLY:
+ cr = some_types[j].ptr;
+ break;
+ case LIB_STATS_ACCESS_WRITE_ONLY:
+ cw = some_types[j].w_ptr;
+ break;
+ case LIB_STATS_ACCESS_READ_WRITE:
+ cr = some_types[j].ptr;
+ cw = some_types[j].w_ptr;
+ break;
+ default:
+ dbg_assert_default ();
+ }
+ lib_stats_set_stat_callback (name[pos], cr, cw,
+ some_types[j].size);
+ }
+ }
+ }
+
+ /* Set some default values. */
+ value_u8 = 0x01;
+ value_u16 = 0x0123;
+ value_u32 = 0x01234567ul;
+ value_u64 = 0x0123456789ABCDEFull;
+
+ /* Do some tests. */
+ /* Not writable. */
+ test_fail_if (lib_stats_write_stat ("read_v_1", "0x42") != false);
+ test_fail_if (value_u8 != 0x1);
+ test_fail_if (lib_stats_write_stat ("read_v_2", "0x42") != false);
+ test_fail_if (value_u16 != 0x0123);
+ test_fail_if (lib_stats_write_stat ("read_v_4", "0x42") != false);
+ test_fail_if (value_u32 != 0x01234567ul);
+ test_fail_if (lib_stats_write_stat ("read_v_8", "0x42") != false);
+ test_fail_if (value_u64 != 0x0123456789ABCDEFull);
+
+ /* Write only. */
+ test_fail_if (lib_stats_write_stat ("write_v_1", "0x42") != true);
+ test_fail_if (value_u8 != 0x42);
+ test_fail_if (lib_stats_write_stat ("write_v_2", "0x4321") != true);
+ test_fail_if (value_u16 != 0x4321);
+ test_fail_if (lib_stats_write_stat ("write_v_4", "0x76543210")
+ != true);
+ test_fail_if (value_u32 != 0x76543210ul);
+ test_fail_if (lib_stats_write_stat ("write_v_8",
+ "0xFEDCBA9876543210") != true);
+ test_fail_if (value_u64 != 0xFEDCBA9876543210ull);
+
+ /* Read/write. */
+ test_fail_if (lib_stats_write_stat ("read_write_v_1", "0x24")
+ != true);
+ test_fail_if (value_u8 != 0x24);
+ test_fail_if (lib_stats_write_stat ("read_write_v_2", "0x2424")
+ != true);
+ test_fail_if (value_u16 != 0x2424);
+ test_fail_if (lib_stats_write_stat ("read_write_v_4", "0x24242424")
+ != true);
+ test_fail_if (value_u32 != 0x24242424ul);
+ test_fail_if (lib_stats_write_stat ("read_write_v_8",
+ "0x2424242424242424") != true);
+ test_fail_if (value_u64 != 0x2424242424242424ull);
+
+ /* Un-decodable values. */
+ test_fail_if (lib_stats_write_stat ("read_write_v_1", "") != false);
+ test_fail_if (lib_stats_write_stat ("read_write_v_1", "x") != false);
+
+ /* Callback read only. */
+ test_fail_if (lib_stats_write_stat ("read_c_1", "0x42") != false);
+ test_fail_if (value_u8 != 0x24);
+ test_fail_if (lib_stats_write_stat ("read_c_2", "0x42") != false);
+ test_fail_if (value_u16 != 0x2424);
+ test_fail_if (lib_stats_write_stat ("read_c_4", "0x42") != false);
+ test_fail_if (value_u32 != 0x24242424l);
+ test_fail_if (lib_stats_write_stat ("read_c_8", "0x42") != false);
+ test_fail_if (value_u64 != 0x2424242424242424ll);
+
+ /* Callback write only. */
+ test_fail_if (lib_stats_write_stat ("write_c_1", "0x42") != true);
+ test_fail_if (value_u8 != 0x42);
+ test_fail_if (lib_stats_write_stat ("write_c_2", "0x4242") != true);
+ test_fail_if (value_u16 != 0x4242);
+ test_fail_if (lib_stats_write_stat ("write_c_4", "0x42424242l")
+ != true);
+ test_fail_if (value_u32 != 0x42424242l);
+ test_fail_if (lib_stats_write_stat ("write_c_8",
+ "0x4242424242424242ll") != true);
+ test_fail_if (value_u64 != 0x4242424242424242ll);
+
+ /* Callback read/write. */
+ test_fail_if (lib_stats_write_stat ("read_write_c_1", "0x24")
+ != true);
+ test_fail_if (value_u8 != 0x24);
+ test_fail_if (lib_stats_write_stat ("read_write_c_2", "0x2424")
+ != true);
+ test_fail_if (value_u16 != 0x2424);
+ test_fail_if (lib_stats_write_stat ("read_write_c_4", "0x24242424l")
+ != true);
+ test_fail_if (value_u32 != 0x24242424l);
+ test_fail_if (lib_stats_write_stat ("read_write_c_8",
+ "0x2424242424242424ll") != true);
+ test_fail_if (value_u64 != 0x2424242424242424ll);
+
+ /* Overflow. */
+ test_fail_if (lib_stats_write_stat ("read_write_c_1", "0x4242")
+ != false);
+ test_fail_if (lib_stats_write_stat ("read_write_v_1", "0x4242")
+ != false);
+
+ lib_stats_uninit ();
+ } test_end;
+}
+
void
stats_test_suite (test_t t)
{
@@ -251,6 +544,14 @@ stats_test_suite (test_t t)
stats_page_update_test_case (t);
stats_stat_update_test_case (t);
stats_many_pages_test_case (t);
+
+ stats_access_mode_test_case (t);
+
+ test_begin (t, "memory")
+ {
+ test_fail_unless (blk_check_memory ());
+ } test_end;
+
}
int
diff --git a/cesar/mac/sar/src/sar.c b/cesar/mac/sar/src/sar.c
index a27e61c90c..0942099229 100644
--- a/cesar/mac/sar/src/sar.c
+++ b/cesar/mac/sar/src/sar.c
@@ -344,10 +344,13 @@ sar_stats_init (sar_stats_t *ctx)
ctx->rx_pb_crc_error_count = 0;
ctx->ber_sum = 0;
/* Register our statistics. */
- lib_stats_set_stat_value_notype ("rx_pb_count", &ctx->rx_pb_count);
+ lib_stats_set_stat_value_notype ("rx_pb_count", &ctx->rx_pb_count,
+ LIB_STATS_ACCESS_READ_ONLY);
lib_stats_set_stat_value_notype ("rx_pb_crc_error_count",
- &ctx->rx_pb_crc_error_count);
- lib_stats_set_stat_value_notype ("ber_sum", &ctx->ber_sum);
+ &ctx->rx_pb_crc_error_count,
+ LIB_STATS_ACCESS_READ_ONLY);
+ lib_stats_set_stat_value_notype ("ber_sum", &ctx->ber_sum,
+ LIB_STATS_ACCESS_READ_ONLY);
}
#endif
diff --git a/cesar/test_general/station/common/src/station.c b/cesar/test_general/station/common/src/station.c
index 54d0c60ec0..1dde0a364f 100644
--- a/cesar/test_general/station/common/src/station.c
+++ b/cesar/test_general/station/common/src/station.c
@@ -59,7 +59,9 @@ lib_stats_callback_test(void)
{
callback_local_value++;
- lib_stats_set_stat_value_notype (callback_local_value_name, &callback_local_value);
+ lib_stats_set_stat_value_notype (callback_local_value_name,
+ &callback_local_value,
+ LIB_STATS_ACCESS_READ_ONLY);
return &callback_local_value;
}
@@ -141,7 +143,10 @@ cyg_user_start (void)
#endif
#if CONFIG_STATS
- lib_stats_set_stat_callback_notype ("idemButCallback(u64)", lib_stats_callback_test);
+ lib_stats_set_stat_callback ("idemButCallback(u64)",
+ (lib_stats_cb_r_t) lib_stats_callback_test,
+ NULL,
+ sizeof (*(lib_stats_callback_test ())));
#endif
return 0;