Annotation of 43BSDTahoe/new/pathalias/mapit.c, revision 1.1.1.1

1.1       root        1: /* pathalias -- by steve bellovin, as told to peter honeyman */
                      2: #ifndef lint
                      3: static char    *sccsid = "@(#)mapit.c  8.1 (down!honey) 86/01/19";
                      4: #endif
                      5: 
                      6: #include "def.h"
                      7: 
                      8: /* privates */
                      9: extern void    reheap(), insert(), heapswap();
                     10: extern link    *min_node(), *rmlink();
                     11: extern Cost    costof();
                     12: 
                     13: static long    Nheap;
                     14: static long    Heaphighwater;
                     15: static link    **Heap;
                     16: 
                     17: 
                     18: /* transform the graph to a shortest-path tree by marking tree edges */
                     19: 
                     20: mapit()
                     21: {
                     22:        register node *n, *next;
                     23:        register link *l;
                     24:        link    *lprev, *lnext;
                     25:        Cost cost;
                     26: 
                     27:        /*
                     28:         * re-use the hash table space for the heap.
                     29:         */
                     30:        Heap = (link **) Table;
                     31: 
                     32:        pack();         /* remove holes in the Table */
                     33:        if (Linkout && *Linkout)        /* dump cheapest links */
                     34:                showlinks();
                     35:        if (Graphout && *Graphout)      /* dump the edge list */
                     36:                dumpgraph();
                     37: 
                     38:        /* invent and insert a link for Home to get things started */
                     39:        l = newlink();
                     40:        l->l_to = Home;
                     41:        (void) dehash(Home);
                     42:        insert(l);
                     43: 
                     44:        /* main mapping loop */
                     45: remap:
                     46:        Heaphighwater = Nheap;
                     47:        while ((l = min_node()) != 0) {
                     48:                l->l_flag |= LTREE;
                     49:                n = l->l_to;
                     50:                n->n_flag |= MAPPED;
                     51:  
                     52:                /* add children to heap */
                     53:                lprev = 0;
                     54:                for (l = n->n_link; l != 0; l = lnext) {
                     55: 
                     56:                        next = l->l_to;         /* neighboring node */
                     57:                        if (next->n_flag & MAPPED) {
                     58:                                lnext = rmlink(l, lprev, n);
                     59:                                continue;
                     60:                        }
                     61:                        cost = costof(n, l);
                     62: 
                     63:                        if (skiplink(l, n, cost)) {
                     64:                                lnext = rmlink(l, lprev, n);
                     65:                                continue;
                     66:                        }
                     67: 
                     68:                        /*
                     69:                         * put this link in the heap, in a place where it may
                     70:                         * percolate up, but not down.  if new, or if cost is
                     71:                         * being increased, move to end.  otherwise, cost is
                     72:                         * same or less, so leave it where it is.  unfortunately,
                     73:                         * freeing a link already in the heap is too costly at
                     74:                         * this point.
                     75:                         *
                     76:                         * TODO: avoid heaping aliases and network members.
                     77:                         */
                     78:                        if (dehash(next) == 0)  /* first time in heap */
                     79:                                insert(l);      /* insert at end */
                     80:                        else {
                     81:                                /* replace heaped link by this one */
                     82:                                if (cost > next->n_cost) {      /* gateway */
                     83:                                        /* move old link to end of heap */
                     84:                                        heapswap((long) (next->n_tloc), Nheap);
                     85:                                        next->n_tloc = Nheap;
                     86:                                }
                     87:                                Heap[next->n_tloc] = l;
                     88:                        }
                     89:                                
                     90:                        next->n_cost = cost;
                     91:                        next->n_parent = n;
                     92:                        reheap(l);              /* restore heap property */
                     93: 
                     94:                        /*
                     95:                         * note whether we got here via a gatewayed net.
                     96:                         * domains are presumed to require gateways.
                     97:                         * aliases inherit parent's gateway status.
                     98:                         */
                     99:                        next->n_flag &= ~GATEWAYIN;
                    100:                        if (l->l_flag & LALIAS)
                    101:                                next->n_flag |= (n->n_flag & GATEWAYIN);
                    102:                        else if (GATEWAYED(n))
                    103:                                next->n_flag |= GATEWAYIN;
                    104:                        lprev = l;      /* this link's a keeper */
                    105:                        lnext = l->l_next;
                    106:                }
                    107: 
                    108:        }
                    109:        vprintf(stderr, "heap high water mark was %d\n", Heaphighwater);
                    110: 
                    111:        /* sanity check on implementation */
                    112:        if (Nheap != 0) {
                    113:                fprintf(stderr, "%s: null entry found in heap\n", ProgName);
                    114:                badmagic(1);
                    115:        }
                    116: 
                    117:        if (Hashpart < Tabsize) {
                    118:                /*
                    119:                 * add back links from unreachable hosts to reachable
                    120:                 * neighbors, then remap.  asymptotically, this is
                    121:                 * quadratic.  in practice, this is done exactly once.
                    122:                 */
                    123:                backlinks();
                    124:                if (Nheap)
                    125:                        goto remap;
                    126:        }
                    127:        if (Hashpart < Tabsize) {
                    128:                fputs("You can't get there from here:\n", stderr);
                    129:                for ( ; Hashpart < Tabsize; Hashpart++) {
                    130:                        fprintf(stderr, "\t%s", Table[Hashpart]->n_name);
                    131:                        if (Table[Hashpart]->n_flag & (ISPRIVATE|COLLISION))
                    132:                                fputs(" (private)", stderr);
                    133:                        putc('\n', stderr);
                    134:                }
                    135:        }
                    136: }
                    137: 
                    138: /*
                    139:  * can this link be ignored?  if yes, return 1, o.w. 0.
                    140:  * a link can be skipped if it is not in the shortest path tree.
                    141:  */
                    142: STATIC int
                    143: skiplink(l, parent, cost)
                    144: link   *l;                     /* new link to this node */
                    145: node   *parent;                /* new parent of this node */
                    146: Cost   cost;                   /* new cost to this node */
                    147: {
                    148:        node    *n;             /* this node */
                    149:        link    *lheap;         /* existing link to this node */
                    150: 
                    151:        n = l->l_to;
                    152: 
                    153:        /* first time we've reached this node? */
                    154:        if (n->n_tloc >= Hashpart)
                    155:                return(0);
                    156: 
                    157:        lheap = Heap[n->n_tloc];
                    158: 
                    159:        /* examine links to nets that require gateways */
                    160:        if (GATEWAYED(n)) {
                    161:                /* if exactly one is a gateway, use it */
                    162:                if ((lheap->l_flag & LGATEWAY) && !(l->l_flag & LGATEWAY))
                    163:                        return(1);      /* old is gateway */
                    164:                if (!(lheap->l_flag & LGATEWAY) && (l->l_flag & LGATEWAY))
                    165:                        return(0);      /* new is gateway */
                    166: 
                    167:                /* no gateway or both gateways;  resolve in standard way ... */
                    168:        }
                    169: 
                    170:        /* examine dup link (sanity check) */
                    171:        if (n->n_parent == parent && ((lheap->l_flag & LDEAD) || (l->l_flag & LDEAD))) {
                    172:                fprintf(stderr, "%s: dup dead link not eliminated: %s -> %s\n",
                    173:                        ProgName, parent->n_name, n->n_name);
                    174:                badmagic(1);
                    175:        }
                    176: 
                    177: 
                    178:        /*  examine cost */
                    179:        if (cost < n->n_cost)
                    180:                return(0);
                    181:        if (cost > n->n_cost)
                    182:                return(1);
                    183: 
                    184:        /* all other things being equal, consult the oracle */
                    185:        return(tiebreaker(n, parent));
                    186: }
                    187: 
                    188: STATIC Cost
                    189: costof(prev, l)
                    190: register node  *prev;
                    191: register link  *l;
                    192: {
                    193:        register node   *next;
                    194:        register Cost   cost;
                    195: 
                    196:        next = l->l_to;
                    197: 
                    198:        if (l->l_flag & LALIAS) {
                    199:                /* copy left/right bits */
                    200:                next->n_flag &= ~(HASLEFT|HASRIGHT);
                    201:                next->n_flag |= (prev->n_flag & (HASLEFT|HASRIGHT));
                    202:                return(prev->n_cost);   /* by definition */
                    203:        }
                    204: 
                    205:                
                    206:        cost = prev->n_cost + l->l_cost;        /* basic cost */
                    207: 
                    208:        /*
                    209:         * heuristics:
                    210:         *    charge for a dead link.
                    211:         *    charge for getting out of a dead host.
                    212:         *    charge for getting into a gatewayed net (except at a gateway).
                    213:         *    discourage mixing of left and right syntax when next is a host.
                    214:         *    charge for leaving a gatewayed net.
                    215:         *
                    216:         * life was simpler when pathalias computed true shortest paths.
                    217:         */
                    218:        if (l->l_flag & LDEAD)          /* dead link */
                    219:                cost += INF/2;
                    220:        if (DEADHOST(prev))             /* dead host */
                    221:                cost += INF/2;
                    222:        if (GATEWAYED(next) && !(l->l_flag & LGATEWAY)) /* not gateway */
                    223:                cost += INF/2;
                    224:        if (!ISANET(next)) {
                    225:                /* charge for mixed syntax here */
                    226:                if ((NETDIR(l) == LLEFT && (prev->n_flag & HASRIGHT))
                    227:                 || (NETDIR(l) == LRIGHT && (prev->n_flag & HASLEFT)))
                    228:                        cost += DEFCOST;
                    229:        }
                    230:        /*
                    231:         * if reached by a gatewayed net, discourage further links.
                    232:         * this has some relevance to common carriers and the FCC ...
                    233:         * the penalty inheres to hosts, not aliases, nets, or domains.
                    234:         */
                    235:        if ((prev->n_flag & GATEWAYIN) && !ISADOMAIN(prev) && !(prev->n_flag & NNET))
                    236:                cost += INF/2;  /* heavyweight, but appropriate */
                    237: 
                    238:        /* set left/right bits */
                    239:        next->n_flag &= ~(HASLEFT|HASRIGHT);
                    240:        if (NETDIR(l) == LLEFT || (prev->n_flag & HASLEFT))
                    241:                next->n_flag |= HASLEFT;
                    242:        if (NETDIR(l) == LRIGHT || (prev->n_flag & HASRIGHT))
                    243:                next->n_flag |= HASRIGHT;
                    244: 
                    245:        return(cost);
                    246: }
                    247: 
                    248: STATIC link *
                    249: rmlink(l, lprev, n)
                    250: link   *l, *lprev;
                    251: node   *n;
                    252: {
                    253:        link    *lnext;
                    254: 
                    255:        lnext = l->l_next;
                    256:        if (lprev)
                    257:                lprev->l_next = l->l_next;
                    258:        else
                    259:                n->n_link = l->l_next;
                    260:        free((char *) l);
                    261:        return(lnext);
                    262: }
                    263: 
                    264: /*
                    265:  * binary heap implementation of priority queue.
                    266:  * TODO: make the heap smaller by giving inserting a placeholder
                    267:  * for net members when the net is extracted.  this requires storing the
                    268:  * cost of a net in the net node itself -- yuck.  is it worth it?
                    269:  */
                    270: 
                    271: STATIC void
                    272: insert(l)
                    273: link   *l;
                    274: {
                    275:        register node   *n;
                    276: 
                    277:        n = l->l_to;
                    278:        Heap[n->n_tloc] = 0;
                    279:        if (Heap[Nheap+1] != 0) {
                    280:                fprintf(stderr, "%s: heap error in insert\n", ProgName);
                    281:                badmagic(1);
                    282:        }
                    283:        if (Nheap++ == 0) {
                    284:                Heap[1] = l;
                    285:                n->n_tloc = 1;
                    286:                return;
                    287:        }
                    288:        if (Vflag && Nheap > Heaphighwater)
                    289:                Heaphighwater = Nheap;  /* diagnostics */
                    290: 
                    291:        /* insert at the end.  caller must reheap(). */
                    292:        Heap[Nheap] = l;
                    293:        n->n_tloc = Nheap;
                    294: }
                    295: 
                    296: /*
                    297:  * replace existing link in heap by this one, then
                    298:  * "percolate" up the heap by exchanging with the parent
                    299:  */
                    300: STATIC void
                    301: reheap(l)
                    302: link   *l;
                    303: {
                    304:        register long   loc, parent;
                    305:        register Cost   cost;
                    306:        register node   *n, *np;
                    307: 
                    308:        n = l->l_to;
                    309: 
                    310:        cost = n->n_cost;
                    311:        for (loc = n->n_tloc; loc > 1; loc = parent) {
                    312:                parent = loc / 2;
                    313:                /* sanity check on implementation */
                    314:                if (Heap[parent] == 0) {
                    315:                        fprintf(stderr, "%s: heap error in insert\n", ProgName);
                    316:                        badmagic(1);
                    317:                }
                    318:                np = Heap[parent]->l_to;
                    319:                if (cost > np->n_cost)
                    320:                        return;
                    321:                /* move nets below hosts for output stability */
                    322:                if (cost == np->n_cost && ((n->n_flag & NNET) || !(np->n_flag & NNET)))
                    323:                        return;
                    324:                heapswap(loc, parent);
                    325:        }
                    326: }
                    327: 
                    328: /* extract min (== Heap[1]) from heap */
                    329: STATIC link    *
                    330: min_node()
                    331: {
                    332:        link *rval;
                    333:        register link **regheap;
                    334:        register long   i, child;
                    335:        
                    336:        if (Nheap == 0)
                    337:                return(0);
                    338: 
                    339:        regheap = Heap;         /* in register -- heavily used */
                    340:        rval = regheap[1];      /* return this one */
                    341:                        
                    342:        /* move last entry into root, percolate down */
                    343:        regheap[1] = regheap[Nheap];
                    344:        regheap[1]->l_to->n_tloc = 1;
                    345:        regheap[Nheap] = 0;
                    346:        if (--Nheap == 0)
                    347:                return(rval);
                    348: 
                    349:        i = 1;
                    350:        for (;;) {
                    351:                /* swap with smaller child down the tree */
                    352:                child = i * 2;  /* lhs child is 2i, rhs is 2i+1. */
                    353:                if (child >= Nheap)
                    354:                        return(rval);
                    355:                /* use rhs child if smaller than lhs child */
                    356:                if (regheap[child]->l_to->n_cost > regheap[child+1]->l_to->n_cost
                    357:                 || (regheap[child]->l_to->n_cost == regheap[child+1]->l_to->n_cost
                    358:                  && !ISANET(regheap[child+1]->l_to)))
                    359:                        child++;
                    360:                        
                    361:                if (regheap[i]->l_to->n_cost < regheap[child]->l_to->n_cost)
                    362:                        return(rval);
                    363:                /* move nets below hosts for output stability */
                    364:                if (regheap[i]->l_to->n_cost == regheap[child]->l_to->n_cost
                    365:                 && (!ISANET(regheap[i]->l_to) || ISANET(regheap[child]->l_to)))
                    366:                        return(rval);
                    367:                heapswap(i, child);
                    368:                i = child;
                    369:        }
                    370:        /*NOTREACHED*/
                    371: }
                    372: 
                    373: /* exchange Heap[i] and Heap[j] pointers */
                    374: STATIC void
                    375: heapswap(i, j)
                    376: long   i, j;
                    377: {
                    378:        register link   *temp, **regheap;
                    379: 
                    380:        regheap = Heap; /* heavily used -- put in register */
                    381:        temp = regheap[i];
                    382:        regheap[i] = regheap[j];
                    383:        regheap[j] = temp;
                    384:        regheap[j]->l_to->n_tloc = j;
                    385:        regheap[i]->l_to->n_tloc = i;
                    386: }
                    387: 
                    388: /* return 1 if n is already de-hashed (n_tloc < Hashpart), 0 o.w. */
                    389: dehash(n)
                    390: register node  *n;
                    391: {
                    392:        if (n->n_tloc < Hashpart)
                    393:                return(1);
                    394: 
                    395:        /* swap with entry in Table[Hashpart] */
                    396:        Table[Hashpart]->n_tloc = n->n_tloc;
                    397:        Table[n->n_tloc] = Table[Hashpart];
                    398:        Table[Hashpart] = n;
                    399: 
                    400:        n->n_tloc = Hashpart++;
                    401:        return(0);
                    402: }
                    403: 
                    404: backlinks()
                    405: {
                    406:        link *l;
                    407:        node *n, *parent, *nomap;
                    408:        long i;
                    409: 
                    410:        for (i = Hashpart; i < Tabsize; i++) {
                    411:                nomap = Table[i];
                    412:                parent = 0;
                    413:                for (l = nomap->n_link; l; l = l->l_next) {
                    414:                        n = l->l_to;
                    415:                        if (!(n->n_flag & MAPPED))
                    416:                                continue;
                    417:                        if (parent == 0) {
                    418:                                parent = n;
                    419:                                continue;
                    420:                        }
                    421:                        if (n->n_cost > parent->n_cost)
                    422:                                continue;
                    423:                        if (n->n_cost == parent->n_cost) {
                    424:                                nomap->n_parent = parent;
                    425:                                if (tiebreaker(nomap, n))
                    426:                                        continue;
                    427:                        }
                    428:                        parent = n;
                    429:                }
                    430:                if (parent == 0)
                    431:                        continue;
                    432:                (void) dehash(nomap);
                    433:                l = addlink(parent, nomap, INF, DEFNET, DEFDIR);
                    434:                nomap->n_parent = parent;
                    435:                nomap->n_cost = costof(parent, l);
                    436:                insert(l);
                    437:                reheap(l);
                    438:        }
                    439:        vprintf(stderr, "%d backlinks\n", Nheap);
                    440: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.