⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mapit.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/* pathalias -- by steve bellovin, as told to peter honeyman */#ifndef lintstatic char	*sccsid = "@(#)mapit.c	9.16 92/08/25";#endif#include "def.h"#define chkheap(i)	/* void */#define chkgap()	/* int */#define trprint(stream, n) \	fprintf((stream), (n)->n_flag & NTERMINAL ? "<%s>" : "%s", (n)->n_name)/* exports *//* invariant while mapping: Nheap < Hashpart */long Hashpart;		/* start of unreached nodes */long Nheap;		/* end of heap */long NumNcopy, Nlink, NumLcopy;void mapit();/* imports */extern long Nheap, Hashpart, Tabsize, Tcount;extern int Tflag, Vflag;extern node **Table, *Home;extern char *Linkout, *Graphout;extern void freelink(), resetnodes(), printit(), dumpgraph();extern void showlinks(), die();extern long pack(), allocation();extern link *newlink(), *addlink();extern int maptrace(), tiebreaker();extern node *ncopy();/* privates */static long	Heaphighwater;static link	**Heap;STATIC void insert(), heapup(), heapdown(), heapswap(), backlinks();STATIC void setheapbits(), mtracereport(), heapchildren(), otracereport();STATIC link *min_node();STATIC int dehash(), skiplink(), skipterminalalias();STATIC Cost costof();STATIC node *mappedcopy();/* transform the graph to a shortest-path tree by marking tree edges */voidmapit(){	register node *n;	register link *l;	vprintf(stderr, "*** mapping\ttcount = %ld\n", Tcount);	Tflag = Tflag && Vflag;		/* tracing here only if verbose */	/* re-use the hash table space for the heap */	Heap = (link **) Table;	Hashpart = pack(0L, Tabsize - 1);	/* expunge penalties from -a option and make circular copy lists */	resetnodes();	if (Linkout && *Linkout)	/* dump cheapest links */		showlinks();	if (Graphout && *Graphout)	/* dump the edge list */		dumpgraph();	/* insert Home to get things started */	l = newlink();		/* link to get things started */	l->l_to = Home;	(void) dehash(Home);	insert(l);	/* main mapping loop */	do {		Heaphighwater = Nheap;		while ((l = min_node()) != 0) {			l->l_flag |= LTREE;			n = l->l_to;			if (n->n_flag & MAPPED)		/* sanity check */				die("mapped node in heap");			if (Tflag && maptrace(n, n))				otracereport(n);	/* tracing */			chkheap(1); chkgap();		/* debugging */			n->n_flag |= MAPPED;			heapchildren(n);	/* add children to heap */		}		vprintf(stderr, "heap hiwat %d\nalloc %ldk, ncopy = %ld, nlink = %ld, lcopy = %ld\n", Heaphighwater, allocation(), NumNcopy, Nlink, NumLcopy);		if (Nheap != 0)		/* sanity check */			die("null entry in heap");		/*		 * add back links from unreachable hosts to reachable		 * neighbors, then remap.  asymptotically, this is		 * quadratic; in practice, this is done once or twice,		 * when n is small.		 */		backlinks();	} while (Nheap > 0);	if (Hashpart < Tabsize) {		int foundone = 0;		for ( ; Hashpart < Tabsize; Hashpart++) {			if (Table[Hashpart]->n_flag & ISPRIVATE)				continue;			if (foundone++ == 0)				fputs("You can't get there from here:\n", stderr);			putc('\t', stderr);			trprint(stderr, Table[Hashpart]);			putc('\n', stderr);		}	}}STATIC voidheapchildren(n)	register node *n;{	register link *l;	register node *next;	register int mtrace;	register Cost cost;	for (l = n->n_link; l; l = l->l_next) {		next = l->l_to;		/* neighboring node */		mtrace = Tflag && maptrace(n, next);		if (l->l_flag & LTREE)			continue;		if (l->l_flag & LTERMINAL)			l->l_to = next = ncopy(n, l);		if ((n->n_flag & NTERMINAL) && (l->l_flag & LALIAS))			if (skipterminalalias(n, next))				continue;			else				l->l_to = next = ncopy(n, l);		if (next->n_flag & MAPPED) {			if (mtrace)				mtracereport(n, l, "-\talready mapped");			continue;		}		cost = costof(n, l);		if (skiplink(l, n, cost, mtrace))			continue;		/*		 * put this link in the heap and restore the		 * heap property.		 */		if (mtrace) {			if (next->n_parent)				mtracereport(next->n_parent, l, "*\tdrop");			mtracereport(n, l, "+\tadd");		}		next->n_parent = n;		if (dehash(next) == 0) {  /* first time */			next->n_cost = cost;			insert(l);	  /* insert at end */			heapup(l);		} else {			/* replace inferior path */			Heap[next->n_tloc] = l;			if (cost > next->n_cost) {				/* increase cost (gateway) */				next->n_cost = cost;				heapdown(l);			} else if (cost < next->n_cost) {				/* cheaper route */				next->n_cost = cost;				heapup(l);			}		}		setheapbits(l);		chkheap(1);	}}/* * n is a terminal node just sucked out of the heap, next is an alias * for n.  if n was heaped because of a copy (ALTEREGO) of next, don't * heap next -- it will happen over and over and over and ... */STATIC intskipterminalalias(n, next)	node *n, *next;{	while (n->n_flag & NALIAS) {		n = n->n_parent;		if (ALTEREGO(n, next))			return 1;	}	return 0;}/* * return 1 if we definitely don't want want this link in the * shortest path tree, 0 if we might want it, i.e., best so far. * * if tracing is turned on, report only if this node is being skipped. */STATIC intskiplink(l, parent, cost, trace)	link *l;		/* new link to this node */	node *parent;		/* (potential) new parent of this node */	register Cost cost;	/* new cost to this node */	int trace;		/* trace this link? */{	register node *n;	/* this node */	register link *lheap;		/* old link to this node */	n = l->l_to;	/* first time we've reached this node? */	if (n->n_tloc >= Hashpart)		return 0;	lheap = Heap[n->n_tloc];	/* examine links to nets that require gateways */	if (GATEWAYED(n)) {		/* if exactly one is a gateway, use it */		if ((lheap->l_flag & LGATEWAY) && !(l->l_flag & LGATEWAY)) {			if (trace)				mtracereport(parent, l, "-\told gateway");			return 1;	/* old is gateway */		}		if (!(lheap->l_flag & LGATEWAY) && (l->l_flag & LGATEWAY))			return 0;	/* new is gateway */		/* no gateway or both gateways;  resolve in standard way ... */	}	/* examine dup link (sanity check) */	if (n->n_parent == parent && (DEADLINK(lheap) || DEADLINK(l)))		die("dup dead link");	/*  examine cost */	if (cost < n->n_cost)		return 0;	if (cost > n->n_cost) {		if (trace)			mtracereport(parent, l, "-\tcheaper");		return 1;	}	/* all other things being equal, ask the oracle */	if (tiebreaker(n, parent)) {		if (trace)			mtracereport(parent, l, "-\ttiebreaker");		return 1;	}	return 0;}/* compute cost to next (l->l_to) via prev */STATIC Costcostof(prev, l)	register node *prev;	register link *l;{	register node *next;	register Cost cost;	if (l->l_flag & LALIAS)		return prev->n_cost;	/* by definition */	next = l->l_to;	cost = prev->n_cost + l->l_cost;	/* basic cost */	if (cost >= INF)		return cost + 1;	/*	 * heuristics:	 *    charge for a dead link.	 *    charge for getting past a terminal host	 *    	or getting out of a dead host.	 *    charge for getting into a gatewayed net (except at a gateway).	 *    discourage mixing of syntax (when prev is a host).	 *	 * life was simpler when pathalias truly computed shortest paths.	 */	if (DEADLINK(l))		cost += INF;				/* dead link */	else if (DEADHOST(prev))		cost += INF;				/* dead parent */	else if (GATEWAYED(next) && !(l->l_flag & LGATEWAY))		cost += INF;				/* not gateway */	else if (!ISANET(prev)) {		if ((NETDIR(l) == LLEFT && (prev->n_flag & HASRIGHT))		 || (NETDIR(l) == LRIGHT && (prev->n_flag & HASLEFT)))			cost += INF;			/* mixed syntax */	}	return cost;}/* binary heap implementation of priority queue */STATIC voidinsert(l)	link *l;{	register node *n;	n = l->l_to;	if (n->n_flag & MAPPED)		die("insert mapped node");	Heap[n->n_tloc] = 0;	if (Heap[Nheap+1] != 0)		die("heap error in insert");	if (Nheap++ == 0) {		Heap[1] = l;		n->n_tloc = 1;		return;	}	if (Vflag && Nheap > Heaphighwater)		Heaphighwater = Nheap;	/* diagnostics */	/* insert at the end.  caller must heapup(l). */	Heap[Nheap] = l;	n->n_tloc = Nheap;}/* * "percolate" up the heap by exchanging with the parent.  as in * min_node(), give tiebreaker() a chance to produce better, stable * routes by moving nets and domains close to the root, nets closer * than domains. * * i know this seems obscure, but it's harmless and cheap.  trust me. */STATIC voidheapup(l)	link *l;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -