/************************************************************************/
/*	Routing Protocol Simulator	Relese 1.0	1994/3/17	*/
/*									*/
/*		module 	: routing table management     			*/
/*		file	: set.c						*/
/*									*/
/*   Copyright (c) 1994 by Systems Development Laboratory Hitachi,Ltd.	*/
/*   All rights reserved.						*/
/*----------------------------------------------------------------------*/
/*	UPDATE HISTORY							*/
/*	1995/7/28   add cost cache list routine				*/
/*                      add_SET_cache_list                              */
/*                      search_cache_list                               */
/************************************************************************/
static char copyright[]=
  "@(#)Copyright (c) 1994 by Systems Development Laboratory Hitachi,Ltd.\n All rights researved.\n";

#include "rps.h"
#include "set.h"

struct SET_ITEM *get_specified_SET_item();
struct SET_ITEM *get_SET_items();
struct SET_ITEM *get_min_cost_item_SET();

struct SET_CACHE_LIST *cache_list=NULL;

/*

  print_SET

*/
void print_SET(set)
struct SET *set;
{
    struct SET_ITEM * p;
    
    for (p = get_SET_items(set, NULL); p; p = get_SET_items(set, p)) {
        printf("node = %d, cost = %d, prev = %d\n", p->node, p->cost, p->prev);
    }
}


struct SET *set;

/*

  get_SET_item_count

*/
int get_SET_item_count(set)
struct SET *set;
{
    struct SET_ITEM * p;
    int count = 0;
    
    for (p = get_SET_items(set, NULL); p; p = get_SET_items(set, p)) {
        count++;
    }
    return count;
}

/*

  initialize_SET

*/
void initialize_SET(set)
struct SET *set;
{
    set->count = 0;
}

/*

  get_specified_SET_item

*/
struct SET_ITEM *get_specified_SET_item(set, node)
struct SET *set;
ID node;
{
    struct SET_ITEM * current;
    
    for (current = get_SET_items(set, NULL); current; current = get_SET_items(set, current)) {
        if (current->node == node) {
            return current;
        }
    }
    return NULL;
}

/*

  del_SET

*/
void del_SET(set, node)
struct SET *set;
ID node;
{
    struct SET_ITEM *p;
    
    if ((p = get_specified_SET_item(set, node)) != NULL) {
        p->node = -1;
    }
    return;
}

/*

  get_SET_items

*/
struct SET_ITEM *get_SET_items(set, current)
struct SET *set;
struct SET_ITEM * current;
{
    if (current == NULL) {
        current = set->tbl;
    } else {
        current++;
    }
    for (; current < set->tbl + set->count; current++) {
        if (current->node != -1) {
            return (current);
        }
    }
    return NULL;
}

/*

  register_SET

*/
struct SET_ITEM *register_SET(set, node, cost)
struct SET *set;
ID node;
long cost;
{
    register struct SET_ITEM * p;
    register int i;
    
    if ((p = get_specified_SET_item(set, node)) != NULL) {
        if (p->cost > cost) {
            p->cost = cost;
        }
        return p;
    }
    for (i = 0; i < set->count; i++) {
        if (set->tbl[i].node == -1) {
            set->tbl[i].node = node;
            set->tbl[i].cost = cost;
            return set->tbl + i;
        }
    }
    if (set->count < SET_MAX) {
        set->tbl[set->count].node = node;
        set->tbl[set->count].cost = cost;
        set->count++;
    } else {
        fprintf(stderr,"buffer overflow \n");
        exit(1);
    }
    return &(set->tbl[set->count - 1]);
}

/*

  register_SET_BGP

*/
struct SET_ITEM *register_SET_BGP(set, node, cost, prev)
struct SET *set;
ID node;
long cost;
ID prev;
{
	register struct SET_ITEM * p;
	register int i;

	if ((p = get_specified_SET_item(set, node)) != NULL) {
		if (p->cost > cost) {
			p->cost = cost;
			p->prev = prev;
		} 
		return p;
	} 
	for (i = 0; i < set->count; i++) {
		if (set->tbl[i].node == NIL) {
			set->tbl[i].node = node;
			set->tbl[i].cost = cost;
			set->tbl[i].prev = prev;
			return set->tbl + i;
		}
	}
	if (set->count < SET_MAX) {
		set->tbl[set->count].node = node;
		set->tbl[set->count].cost = cost;
		set->tbl[set->count].prev = prev;
		set->count++;
	} else {
		fprintf(stderr, "Too many set items.\n");
		exit(1);
	}
	return &(set->tbl[set->count - 1]);
}

/*

  get_min_cost_item_SET

*/
struct SET_ITEM *get_min_cost_item_SET(set)
struct SET *set;
{
    struct SET_ITEM * current, *min_item = NULL;
    
    for (current = get_SET_items(set, NULL); current; current = get_SET_items(set, current)) {
        if (min_item == NULL) {
            min_item = current;
        } else {
            if (current->cost < min_item->cost) {
                min_item = current;
            }
        }
    }
    return min_item;
}

/*

  get_path_from_SET

*/
ID get_path_from_SET(set, node)
struct SET *set;
ID node;
{
	struct SET_ITEM * current, *min_item = NULL;
	static ID current_node = NIL;

	if (node != NIL) {
		current_node = node;
		return node;
	} else {
		if (current_node == NIL) {
			return NIL;
		}
	}
	if ((current = get_specified_SET_item(set, current_node)) == NULL) {
		fprintf(stderr, "Can't find previouse node \n");
	/*	exit (1);*/
		return NIL;
	}
	current_node = current->prev;
	return current_node;
}

/*

  get_path_node_count_from_SET

*/
int get_path_node_count_from_SET(set, node)
struct SET *set;
ID node;
{
	int count = 0;

	for(node = get_path_from_SET(set, node); node != NIL; node = get_path_from_SET(set, NIL)) {
		count++;
	}
	return count;
}


/*

  add_SET_cache_list

*/
void add_SET_cache_list(node,set)
ID node;
struct SET *set;
{
    struct SET_CACHE_LIST *list,*cache;

    if((cache=(struct SET_CACHE_LIST *)malloc(sizeof(struct SET_CACHE_LIST))) == NULL) {
	log_trace(stderr,"can't malloc SET_CACHE_LIST\n");
	return ;
    }

    bzero(cache,sizeof(struct SET_CACHE_LIST));
    cache->node = node;
    cache->set = set;
    
    if(cache_list == NULL) {
	cache_list = cache;
    }
    else {
	for(list=cache_list;list->next;list=list->next);
	list->next = cache;
    }

}

/*

  search_cache_list

*/
struct SET *search_cache_list(node)
ID node;
{
    struct SET_CACHE_LIST *list;

    for(list=cache_list;list;list=list->next) {
	if(list->node == node) {
	    return list->set;
	}
    }

    return NULL;
}


void print_SET_cache_list()
{
    struct SET_CACHE_LIST *list;

    for(list=cache_list;list;list=list->next) {
	printf("node = %d SET = %x\n",list->node,list->set);
    }
}
