/**
* Copyright (C) Mellanox Technologies Ltd. 2001-2013.  ALL RIGHTS RESERVED.
*
* See file LICENSE for terms.
*/

#ifdef HAVE_CONFIG_H
#  include "config.h"
#endif

#include "libstats.h"

#include <ucs/debug/log.h>
#include <errno.h>
#include <string.h>


#define UCS_STATS_NAME_VALID_CHARS \
    "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"


static ucs_status_t ucs_stats_name_check(const char *name)
{
    size_t length, valid_length;

    length = strlen(name);
    if (length > UCS_STAT_NAME_MAX) {
        ucs_error("stats name '%s' is too long (%zu)", name, length);
        return UCS_ERR_INVALID_PARAM;
    }

    valid_length = strspn(name, UCS_STATS_NAME_VALID_CHARS);
    if (valid_length != length) {
        ucs_error("stats name '%s' contains invalid character at offset %zu",
                  name, valid_length);
        return UCS_ERR_INVALID_PARAM;
    }

    return UCS_OK;
}

ucs_status_t ucs_stats_node_initv(ucs_stats_node_t *node, ucs_stats_class_t *cls,
                                  const char *name, va_list ap)
{
    ucs_status_t status;
    unsigned i;

    /* Check class */
    status = ucs_stats_name_check(cls->name);
    if (status != UCS_OK) {
        return status;
    }
    for (i = 0; i < cls->num_counters; ++i) {
        status = ucs_stats_name_check(cls->counter_names[i]);
        if (status != UCS_OK) {
            return status;
        }
    }

    /* Set up node */
    node->cls = cls;
    vsnprintf(node->name, UCS_STAT_NAME_MAX, name, ap);
    ucs_list_head_init(&node->children[UCS_STATS_INACTIVE_CHILDREN]);
    ucs_list_head_init(&node->children[UCS_STATS_ACTIVE_CHILDREN]);
    memset(node->counters, 0, cls->num_counters * sizeof(ucs_stats_counter_t));

    return UCS_OK;
}

