summaryrefslogtreecommitdiff
path: root/lib/log.c
diff options
context:
space:
mode:
authorQuentin Young <qlyoung@cumulusnetworks.com>2017-06-20 23:56:50 +0000
committerQuentin Young <qlyoung@cumulusnetworks.com>2017-06-21 15:22:21 +0000
commit56b40679304df9c4bfcfd5764af24f1d35b86142 (patch)
tree755de54cbc890545f73efe5f1f4d1843506d1860 /lib/log.c
parentd368cd48b94cb9a22b9733200d8cfd94c71338ce (diff)
*: simplify log message lookup
log.c provides functionality for associating a constant (typically a protocol constant) with a string and finding the string given the constant. However this is highly delicate code that is extremely prone to stack overflows and off-by-one's due to requiring the developer to always remember to update the array size constant and to do so correctly which, as shown by example, is never a good idea.b The original goal of this code was to try to implement lookups in O(1) time without a linear search through the message array. Since this code is used 99% of the time for debugs, it's worth the 5-6 additional cmp's worst case if it means we avoid explitable bugs due to oversights... Signed-off-by: Quentin Young <qlyoung@cumulusnetworks.com>
Diffstat (limited to 'lib/log.c')
-rw-r--r--lib/log.c82
1 files changed, 26 insertions, 56 deletions
diff --git a/lib/log.c b/lib/log.c
index b55a1c2ecf..a8b221fd64 100644
--- a/lib/log.c
+++ b/lib/log.c
@@ -85,8 +85,33 @@ static void write_wrapper (int fd, const void *buf, size_t count)
return;
}
-/* For time string format. */
+/**
+ * Looks up a message in a message list by key.
+ *
+ * If the message is not found, returns the provided error message.
+ *
+ * Terminates when it hits a struct message that's all zeros.
+ *
+ * @param mz the message list
+ * @param kz the message key
+ * @param nf the message to return if not found
+ * @return the message
+ */
+const char *
+lookup_msg(const struct message *mz, int kz, const char *nf)
+{
+ static struct message nt = { 0 };
+ const char *rz = nf ? nf : "(no message found)";
+ const struct message *pnt;
+ for (pnt = mz; memcmp(pnt, &nt, sizeof(struct message)); pnt++)
+ if (pnt->key == kz) {
+ rz = pnt->str ? pnt->str : rz;
+ break;
+ }
+ return rz;
+}
+/* For time string format. */
size_t
quagga_timestamp(int timestamp_precision, char *buf, size_t buflen)
{
@@ -851,61 +876,6 @@ zlog_rotate (void)
return 1;
}
-/* Message lookup function. */
-const char *
-lookup (const struct message *mes, int key)
-{
- const struct message *pnt;
-
- for (pnt = mes; pnt->key != 0; pnt++)
- if (pnt->key == key)
- return pnt->str;
-
- return "";
-}
-
-/* Older/faster version of message lookup function, but requires caller to pass
- * in the array size (instead of relying on a 0 key to terminate the search).
- *
- * The return value is the message string if found, or the 'none' pointer
- * provided otherwise.
- */
-const char *
-mes_lookup (const struct message *meslist, int max, int index,
- const char *none, const char *mesname)
-{
- int pos = index - meslist[0].key;
-
- /* first check for best case: index is in range and matches the key
- * value in that slot.
- * NB: key numbering might be offset from 0. E.g. protocol constants
- * often start at 1.
- */
- if ((pos >= 0) && (pos < max)
- && (meslist[pos].key == index))
- return meslist[pos].str;
-
- /* fall back to linear search */
- {
- int i;
-
- for (i = 0; i < max; i++, meslist++)
- {
- if (meslist->key == index)
- {
- const char *str = (meslist->str ? meslist->str : none);
-
- zlog_debug ("message index %d [%s] found in %s at position %d (max is %d)",
- index, str, mesname, i, max);
- return str;
- }
- }
- }
- zlog_err("message index %d not found in %s (max is %d)", index, mesname, max);
- assert (none);
- return none;
-}
-
/* Wrapper around strerror to handle case where it returns NULL. */
const char *
safe_strerror(int errnum)