diff options
Diffstat (limited to 'lib/ferr.c')
| -rw-r--r-- | lib/ferr.c | 162 |
1 files changed, 162 insertions, 0 deletions
diff --git a/lib/ferr.c b/lib/ferr.c index 45574520a5..2fa5db6f34 100644 --- a/lib/ferr.c +++ b/lib/ferr.c @@ -19,14 +19,22 @@ #include <string.h> #include <pthread.h> #include <signal.h> +#include <inttypes.h> #include "ferr.h" #include "vty.h" #include "jhash.h" #include "memory.h" +#include "hash.h" +#include "command.h" +#include "json.h" +#include "linklist.h" DEFINE_MTYPE_STATIC(LIB, ERRINFO, "error information") +/* + * Thread-specific key for temporary storage of allocated ferr. + */ static pthread_key_t errkey; static void ferr_free(void *arg) @@ -46,6 +54,160 @@ static void err_key_fini(void) pthread_key_delete(errkey); } +/* + * Global shared hash table holding reference text for all defined errors. + */ +pthread_mutex_t refs_mtx = PTHREAD_MUTEX_INITIALIZER; +struct hash *refs; + +static int ferr_hash_cmp(const void *a, const void *b) +{ + const struct log_ref *f_a = a; + const struct log_ref *f_b = b; + + return f_a->code == f_b->code; +} + +static inline unsigned int ferr_hash_key(void *a) +{ + struct log_ref *f = a; + + return f->code; +} + +void log_ref_add(struct log_ref *ref) +{ + uint32_t i = 0; + + pthread_mutex_lock(&refs_mtx); + { + while (ref[i].code != END_FERR) { + hash_get(refs, &ref[i], hash_alloc_intern); + i++; + } + } + pthread_mutex_unlock(&refs_mtx); +} + +struct log_ref *log_ref_get(uint32_t code) +{ + struct log_ref holder; + struct log_ref *ref; + + holder.code = code; + pthread_mutex_lock(&refs_mtx); + { + ref = hash_lookup(refs, &holder); + } + pthread_mutex_unlock(&refs_mtx); + + return ref; +} + +void log_ref_display(struct vty *vty, uint32_t code, bool json) +{ + struct log_ref *ref; + struct json_object *top, *obj; + struct list *errlist; + struct listnode *ln; + + if (json) + top = json_object_new_object(); + + pthread_mutex_lock(&refs_mtx); + { + errlist = code ? list_new() : hash_to_list(refs); + } + pthread_mutex_unlock(&refs_mtx); + + if (code) { + ref = log_ref_get(code); + if (!ref) { + vty_out(vty, "Code %"PRIu32" - Unknown\n", code); + return; + } + listnode_add(errlist, ref); + } + + for (ALL_LIST_ELEMENTS_RO(errlist, ln, ref)) { + if (json) { + char key[11]; + + snprintf(key, sizeof(key), "%"PRIu32, ref->code); + obj = json_object_new_object(); + json_object_string_add(obj, "title", ref->title); + json_object_string_add(obj, "description", + ref->description); + json_object_string_add(obj, "suggestion", + ref->suggestion); + json_object_object_add(top, key, obj); + } else { + char pbuf[256]; + char ubuf[256]; + + snprintf(pbuf, sizeof(pbuf), "\nError %"PRIu32" - %s", + code, ref->title); + memset(ubuf, '=', strlen(pbuf)); + ubuf[sizeof(ubuf) - 1] = '\0'; + + vty_out(vty, "%s\n%s\n", pbuf, ubuf); + vty_out(vty, "Description:\n%s\n\n", ref->description); + vty_out(vty, "Recommendation:\n%s\n", ref->suggestion); + } + } + + if (json) { + const char *str = json_object_to_json_string_ext( + top, JSON_C_TO_STRING_PRETTY); + vty_out(vty, "%s\n", str); + json_object_free(top); + } + + list_delete_and_null(&errlist); +} + +DEFUN_NOSH(show_error_code, + show_error_code_cmd, + "show error <(1-4294967296)|all> [json]", + SHOW_STR + "Information on errors\n" + "Error code to get info about\n" + "Information on all errors\n" + JSON_STR) +{ + bool json = strmatch(argv[argc-1]->text, "json"); + uint32_t arg = 0; + + if (!strmatch(argv[2]->text, "all")) + arg = strtoul(argv[2]->arg, NULL, 10); + + log_ref_display(vty, arg, json); + return CMD_SUCCESS; +} + +void log_ref_init(void) +{ + pthread_mutex_lock(&refs_mtx); + { + refs = hash_create(ferr_hash_key, ferr_hash_cmp, + "Error Reference Texts"); + } + pthread_mutex_unlock(&refs_mtx); + + install_element(VIEW_NODE, &show_error_code_cmd); +} + +void log_ref_fini(void) +{ + pthread_mutex_lock(&refs_mtx); + { + hash_clean(refs, NULL); + hash_free(refs); + refs = NULL; + } + pthread_mutex_unlock(&refs_mtx); +} + const struct ferr *ferr_get_last(ferr_r errval) { struct ferr *last_error = pthread_getspecific(errkey); |
