/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

#include <qpid/dispatch/trace_mask.h>
#include <qpid/dispatch/iterator.h>
#include <qpid/dispatch/threading.h>
#include <qpid/dispatch/hash.h>
#include "alloc.h"

typedef struct {
    qd_hash_handle_t *hash_handle;
    int               maskbit;
    int               link_maskbit;
} qdtm_router_t;

ALLOC_DECLARE(qdtm_router_t);
ALLOC_DEFINE(qdtm_router_t);

struct qd_tracemask_t {
    sys_rwlock_t   *lock;
    qd_hash_t      *hash;
    qdtm_router_t **router_by_mask_bit;
};


qd_tracemask_t *qd_tracemask(void)
{
    qd_tracemask_t *tm = NEW(qd_tracemask_t);
    tm->lock               = sys_rwlock();
    tm->hash               = qd_hash(8, 1, 0);
    tm->router_by_mask_bit = NEW_PTR_ARRAY(qdtm_router_t, qd_bitmask_width());

    for (int i = 0; i < qd_bitmask_width(); i++)
        tm->router_by_mask_bit[i] = 0;
    return tm;
}


void qd_tracemask_free(qd_tracemask_t *tm)
{
    for (int i = 0; i < qd_bitmask_width(); i++) {
        if (tm->router_by_mask_bit[i])
            qd_tracemask_del_router(tm, i);
    }

    qd_hash_free(tm->hash);
    sys_rwlock_free(tm->lock);
    free(tm);
}


void qd_tracemask_add_router(qd_tracemask_t *tm, const char *address, int maskbit)
{
    qd_field_iterator_t *iter = qd_address_iterator_string(address, ITER_VIEW_ADDRESS_HASH);
    sys_rwlock_wrlock(tm->lock);
    assert(maskbit < qd_bitmask_width() && tm->router_by_mask_bit[maskbit] == 0);
    if (maskbit < qd_bitmask_width() && tm->router_by_mask_bit[maskbit] == 0) {
        qdtm_router_t *router = new_qdtm_router_t();
        router->maskbit = maskbit;
        router->link_maskbit = -1;
        qd_hash_insert(tm->hash, iter, router, &router->hash_handle);
        tm->router_by_mask_bit[maskbit] = router;
    }
    sys_rwlock_unlock(tm->lock);
    qd_field_iterator_free(iter);
}


void qd_tracemask_del_router(qd_tracemask_t *tm, int maskbit)
{
    sys_rwlock_wrlock(tm->lock);
    assert(maskbit < qd_bitmask_width() && tm->router_by_mask_bit[maskbit] != 0);
    if (maskbit < qd_bitmask_width() && tm->router_by_mask_bit[maskbit] != 0) {
        qdtm_router_t *router = tm->router_by_mask_bit[maskbit];
        qd_hash_remove_by_handle(tm->hash, router->hash_handle);
        tm->router_by_mask_bit[maskbit] = 0;
        free_qdtm_router_t(router);
    }
    sys_rwlock_unlock(tm->lock);
}


void qd_tracemask_set_link(qd_tracemask_t *tm, int router_maskbit, int link_maskbit)
{
    sys_rwlock_wrlock(tm->lock);
    assert(router_maskbit < qd_bitmask_width() && link_maskbit < qd_bitmask_width() &&
           tm->router_by_mask_bit[router_maskbit] != 0);
    if (router_maskbit < qd_bitmask_width() && link_maskbit < qd_bitmask_width() &&
        tm->router_by_mask_bit[router_maskbit] != 0) {
        qdtm_router_t *router = tm->router_by_mask_bit[router_maskbit];
        router->link_maskbit = link_maskbit;
    }
    sys_rwlock_unlock(tm->lock);
}


void qd_tracemask_remove_link(qd_tracemask_t *tm, int router_maskbit)
{
    sys_rwlock_wrlock(tm->lock);
    assert(router_maskbit < qd_bitmask_width() && tm->router_by_mask_bit[router_maskbit] != 0);
    if (router_maskbit < qd_bitmask_width() && tm->router_by_mask_bit[router_maskbit] != 0) {
        qdtm_router_t *router = tm->router_by_mask_bit[router_maskbit];
        router->link_maskbit = -1;
    }
    sys_rwlock_unlock(tm->lock);
}


qd_bitmask_t *qd_tracemask_create(qd_tracemask_t *tm, qd_parsed_field_t *tracelist)
{
    qd_bitmask_t *bm  = qd_bitmask(0);
    int           idx = 0;

    assert(qd_parse_is_list(tracelist));

    sys_rwlock_rdlock(tm->lock);
    qd_parsed_field_t *item   = qd_parse_sub_value(tracelist, idx);
    qdtm_router_t     *router = 0;
    while (item) {
        qd_field_iterator_t *iter = qd_parse_raw(item);
        qd_address_iterator_reset_view(iter, ITER_VIEW_NODE_HASH);
        qd_hash_retrieve(tm->hash, iter, (void*) &router);
        if (router && router->link_maskbit >= 0)
            qd_bitmask_set_bit(bm, router->link_maskbit);
        idx++;
        item = qd_parse_sub_value(tracelist, idx);
    }
    sys_rwlock_unlock(tm->lock);
    return bm;
}

