int vfs_main(int argc,char **argv){ unused(argc,argv); vfs_init(); dorun(); return 0; }
// add compound hops int compound(gnet *net) { ub4 rportcnt,rport2,portcnt = net->portcnt; ub4 hopcnt = net->hopcnt; ub4 hop,chop,chopcnt,newhopcnt = 0,newcnt; ub4 rid,rrid,ridcnt = net->ridcnt; ub4 chain,chaincnt = net->chaincnt; ub4 hichainlen = net->hichainlen; ub4 hiportlen; struct hop *hp,*hp1,*hp2,*hops = net->hops; struct port *pdep,*parr,*ports = net->ports; struct route *rp,*routes = net->routes; struct chain *cp,*chains = net->chains; struct chainhop *chp,*chainhops = net->chainhops; ub8 *crp,*chainrhops = net->chainrhops; ub4 maxperm = min(cmp_maxperm,Chainlen); ub4 maxperm2 = maxperm * maxperm; ub4 dep,arr,deparr,da,prvda,rdep,rarr; int docompound; net->chopcnt = hopcnt; if (hopcnt == 0) return info(0,"skip compound on %u hop\as",hopcnt); net->hopcdur = alloc(hopcnt,ub4,0xff,"net hopcdur",hopcnt); // fallback if (portcnt < 3) return info(0,"skip compound on %u port\as",portcnt); if (hopcnt < 2) return info(0,"skip compound on %u hop\as",hopcnt); if (ridcnt == 0) return info(0,"skip compound on no rids for %u hop\as",hopcnt); docompound = dorun(FLN,Runcompound,1); if (docompound == 0) return info0(0,"compound not enabled"); info(0,"compounding %u ports %u hops max chain %u",portcnt,hopcnt,hichainlen); ub4 *orgportsbyhop = net->portsbyhop; ub4 *orghopdist = net->hopdist; ub4 *orghopdur = net->hopdur; ub4 midur,dur,sumdur,durdif; ub4 hop1,hop2,rhop1,rhop2,dep1,arr2; ub4 dist1,dist2,dist = 0,dirdist; ub4 tdep,tarr,tdep1,tarr2; ub4 ci,ci1,ci2,pchlen,cmpcnt; ub4 pchain[Chainlen]; ub4 pdeps[Chainlen]; ub4 parrs[Chainlen]; ub4 ptdep[Chainlen]; ub4 ptarr[Chainlen]; ub4 pdist[Chainlen]; error_zp(orghopdist,hopcnt); ub4 cnt,cmphopcnt = 0; error_z(chaincnt,ridcnt); error_zp(routes,0); error_zp(chains,0); struct eta eta; int warnlim; ub8 cumfevcnt = 0,cumcfevcnt = 0; ub4 cumfhops = 0; ub4 hicnt = 0,hirid = 0; for (rid = 0; rid < ridcnt; rid++) { rp = routes + rid; if (rp->hopcnt > hicnt) { hicnt = rp->hopcnt; hirid = rid; } } rp = routes + hirid; info(0,"r.rid %u.%u has %u hops for len %u",rp->rrid,hirid,hicnt,rp->hichainlen); hiportlen = max(hichainlen,hicnt) + 10; ub4 hiport2 = hiportlen * hiportlen; ub4 *port2rport = alloc(portcnt,ub4,0,"cmp rportmap",portcnt); ub4 *rport2port = alloc(hiportlen,ub4,0,"cmp rportmap",hiportlen); ub4 *duphops = alloc(hiport2,ub4,0xff,"cmp duphops",hiportlen); ub4 *cduphops = alloc(hiport2,ub4,0xff,"cmp cduphops",hiportlen); ub4 *rport2hop = alloc(hiport2,ub4,0xff,"cmp rport2hop",hiportlen); ub4 *rhopcdur = alloc(hiport2,ub4,0,"cmp hopcdur",newhopcnt); ub4 *hopccnt = alloc(hiport2,ub4,0,"cmp hopccnt",newhopcnt); ub4 *hoplodur = alloc(hiport2,ub4,0,"cmp hoplodur",newhopcnt); ub4 *hophidur = alloc(hiport2,ub4,0,"cmp hophidur",newhopcnt); ub4 port2 = portcnt * portcnt; ub4 *duprids = alloc(port2,ub4,0xff,"cmp duprids",portcnt); // pass 1: count for (rid = 0; rid < ridcnt; rid++) { if (progress(&eta,"compound rid %u of %u for %u chains pass 1",rid,ridcnt,chaincnt)) return 1; rp = routes + rid; rrid = rp->rrid; nsethi(port2rport,portcnt); rportcnt = 0; for (hop = 0; hop < hopcnt; hop++) { hp = hops + hop; if (hp->rid != rid) continue; dep = hp->dep; arr = hp->arr; if (dep == arr) continue; deparr = dep * portcnt + arr; if (duprids[deparr] == rid) { warn(Iter,"duplicate hop %u %u-%u for rid %u",hop,dep,arr,rid); continue; } duprids[deparr] = rid; if (hp->reserve) { cumfevcnt += hp->tp.evcnt; cumfhops++; } if (port2rport[dep] == hi32) { error_ge(rportcnt,hiportlen); port2rport[dep] = rportcnt; rport2port[rportcnt++] = dep; } if (port2rport[arr] == hi32) { error_ge_cc(rportcnt,hiportlen,"rrid %u len %u cnt %u",rrid,rp->hichainlen,rp->hopcnt); port2rport[arr] = rportcnt; rport2port[rportcnt++] = arr; } } warncc(rportcnt >= hiportlen,0,"r.rid %u.%u len %u above %u",rrid,rid,rportcnt,hiportlen); rportcnt = min(rportcnt,hiportlen); rport2 = rportcnt * rportcnt; nsethi(duphops,rport2); newcnt = 0; for (rdep = 0; rdep < rportcnt; rdep++) duphops[rdep * rportcnt + rdep] = 0; warnlim = 1; for (chain = 0; chain < chaincnt; chain++) { cp = chains + chain; cnt = cp->hopcnt; if (cp->rid != rid || cnt < 3) continue; pchlen = 0; for (ci = 0; ci < cnt; ci++) { chp = chainhops + cp->hopofs + ci; hop = chp->hop; error_ge(hop,hopcnt); if (pchlen == maxperm) { warncc(warnlim,0,"limiting rid %u chain to %u",rid,maxperm); warnlim = 0; break; } dep = orgportsbyhop[hop * 2]; arr = orgportsbyhop[hop * 2 + 1]; error_ge(dep,portcnt); error_ge(arr,portcnt); if (dep == arr) continue; rdep = port2rport[dep]; rarr = port2rport[arr]; error_ge(rdep,rportcnt); error_ge(rarr,rportcnt); pdeps[pchlen] = rdep; parrs[pchlen] = rarr; tdep = chp->tdep; tarr = chp->tarr; error_lt(tarr,tdep); pchlen++; } if (pchlen < 3) continue; // generate all not yet existing compounds memcpy(cduphops,duphops,rport2 * sizeof(*duphops)); cmpcnt = 0; for (ci1 = 0; ci1 < pchlen - 1; ci1++) { dep1 = pdeps[ci1]; for (ci2 = ci1 + 1; ci2 < pchlen; ci2++) { arr2 = parrs[ci2]; if (dep1 == arr2) continue; deparr = dep1 * rportcnt + arr2; if (cduphops[deparr] != hi32) continue; duphops[deparr] = 0; cmpcnt++; if (cmpcnt >= maxperm2) break; } // each c2 if (cmpcnt >= maxperm2) { warning(0,"limiting compound on rid %u to %u combis",rid,cmpcnt); break; } } // each c1 newcnt += cmpcnt; } // each chain cmphopcnt += newcnt; vrb0(0,"rid %u len %u cmp %u",rid,rportcnt,newcnt); } // each rid info(0,"\ah%u compound hops added to \ah%u",cmphopcnt,hopcnt); if (cmphopcnt == 0) return 0; info(0,"compound %u chains in %u rids pass 2",chaincnt,ridcnt); newhopcnt = cmphopcnt + hopcnt; chop = hopcnt; ub4 *portsbyhop = alloc(newhopcnt * 2,ub4,0,"cmp portsbyhop",newhopcnt); memcpy(portsbyhop,orgportsbyhop,hopcnt * 2 * sizeof(ub4)); afree(orgportsbyhop,"net portsbyhop"); net->portsbyhop = portsbyhop; ub4 *hopdist = alloc(newhopcnt,ub4,0,"cmp hopdist",newhopcnt); memcpy(hopdist,orghopdist,hopcnt * sizeof(ub4)); afree(orghopdist,"net hopdist"); net->hopdist = hopdist; ub4 *hopdur = alloc(newhopcnt,ub4,0,"cmp hopdur",newhopcnt); memcpy(hopdur,orghopdur,hopcnt * sizeof(ub4)); afree(orghopdur,"net hopdur"); net->hopdur = hopdur; ub4 *hopcdur = alloc(newhopcnt,ub4,0,"cmp hopcdur",newhopcnt); ub4 *choporg = alloc(newhopcnt * 2,ub4,0,"cmp choporg",newhopcnt); ub8 cumchainlen = 0,pchaincnt = 0; ub4 eqdurs = 0,aeqdurs = 0; ub4 cdist; nsethi(duprids,port2); // pass 2 for (rid = 0; rid < ridcnt; rid++) { if (progress(&eta,"compound rid %u of %u for %u chains pass 2",rid,ridcnt,chaincnt)) return 1; rp = routes + rid; nsethi(port2rport,portcnt); rportcnt = 0; for (hop = 0; hop < hopcnt; hop++) { hp = hops + hop; if (hp->rid != rid) continue; dep = hp->dep; arr = hp->arr; if (dep == arr) continue; deparr = dep * portcnt + arr; if (duprids[deparr] == rid) continue; duprids[deparr] = rid; if (port2rport[dep] == hi32) { port2rport[dep] = rportcnt; rport2port[rportcnt++] = dep; } if (port2rport[arr] == hi32) { port2rport[arr] = rportcnt; rport2port[rportcnt++] = arr; } } rportcnt = min(rportcnt,hiportlen); rport2 = rportcnt * rportcnt; nsethi(duphops,rport2); nclear(rhopcdur,rport2); nclear(hopccnt,rport2); for (chain = 0; chain < chaincnt; chain++) { cp = chains + chain; cnt = cp->hopcnt; if (cp->rid != rid || cnt < 3) continue; pchlen = 0; cdist = 0; for (ci = 0; ci < cnt; ci++) { chp = chainhops + cp->hopofs + ci; hop = chp->hop; dep = portsbyhop[hop * 2]; arr = portsbyhop[hop * 2 + 1]; if (dep == arr) continue; pdep = ports + dep; parr = ports + arr; rdep = port2rport[dep]; rarr = port2rport[arr]; error_ge(rdep,rportcnt); error_ge(rarr,rportcnt); for (ci2 = 0; ci2 < pchlen; ci2++) { hop2 = pchain[ci2]; if (hop != hop2) continue; error(Exit,"rid %u chain %u hop %u pos %u equals pos %u %s to %s",rid,chain,hop,pchlen,ci2,pdep->name,parr->name); } dist = hopdist[hop]; hp = hops + hop; pchain[pchlen] = hop; pdeps[pchlen] = rdep; parrs[pchlen] = rarr; pdist[pchlen] = cdist; ptdep[pchlen] = chp->tdep; ptarr[pchlen] = chp->tarr; cdist += max(dist,1); pchlen++; if (pchlen == maxperm) { warning(0,"limiting rid %u chain to %u",rid,maxperm); break; } } if (pchlen < 3) continue; pchaincnt++; cumchainlen += pchlen; // generate all not yet existing compounds // note that some chains visit ports more than once memcpy(cduphops,duphops,rport2 * sizeof(*duphops)); cmpcnt = 0; for (ci1 = 0; ci1 < pchlen - 1; ci1++) { dep1 = pdeps[ci1]; for (ci2 = ci1 + 1; ci2 < pchlen; ci2++) { arr2 = parrs[ci2]; if (dep1 == arr2) continue; deparr = dep1 * rportcnt + arr2; prvda = cduphops[deparr]; if (prvda != hi32) { // existing: accumulate and range duration tdep1 = ptdep[ci1]; tarr2 = ptarr[ci2]; error_lt(tarr2,tdep1); dur = tarr2 - tdep1; rhopcdur[prvda] += dur; hoplodur[prvda] = min(hoplodur[prvda],dur); hophidur[prvda] = max(hophidur[prvda],dur); hopccnt[prvda]++; continue; } if (chop >= newhopcnt) { warn(0,"limiting compound to %u hops",chop - hopcnt); break; } duphops[deparr] = deparr; rport2hop[deparr] = chop; // generate compound hop1 = pchain[ci1]; hop2 = pchain[ci2]; dist1 = pdist[ci1]; dist2 = pdist[ci2]; tdep1 = ptdep[ci1]; tarr2 = ptarr[ci2]; infocc(dist2 == 0,0,"chop %u dist %u+%u",chop,dist1,dist2); error_eq(hop1,hop2); dep = rport2port[dep1]; arr = rport2port[arr2]; portsbyhop[chop * 2] = dep; portsbyhop[chop * 2 + 1] = arr; choporg[chop * 2] = hop1; choporg[chop * 2 + 1] = hop2; hp1 = hops + hop1; hp2 = hops + hop2; if (hp1->reserve) { cumcfevcnt += hp1->tp.evcnt; cumfhops++; } rhop1 = hp1->rhop; rhop2 = hp2->rhop; crp = chainrhops + cp->rhopofs; error_lt(dist2,dist1); // todo ? dist = dist2 - dist1 + hopdist[hop2]; pdep = ports + dep; parr = ports + arr; dirdist = fgeodist(pdep,parr); hopdist[chop] = max(dist,dirdist); noexit error_lt(tarr2,tdep1); // todo: day wrap ? error_ne(crp[rhop1] >> 32,tdep1); error_ne(crp[rhop2] & hi32,tarr2); if (tarr2 >= tdep1) midur = tarr2 - tdep1; else midur = hi32; hopdur[chop] = midur; // first entry rhopcdur[deparr] = midur; hoplodur[deparr] = midur; hophidur[deparr] = midur; hopccnt[deparr] = 1; chop++; cmpcnt++; } // each c2 if (chop >= newhopcnt) break; else if (cmpcnt >= maxperm2) { warning(0,"limiting compound on rid %u to %u combis",rid,cmpcnt); break; } } // each c1 if (chop >= newhopcnt) break; } // each chain if (chop >= newhopcnt) break; for (deparr = 0; deparr < rport2; deparr++) { da = duphops[deparr]; if (da == hi32) continue; hop = rport2hop[da]; error_ge(hop,chop); cnt = hopccnt[da]; error_z(cnt,hop); error_gt(hoplodur[da],hophidur[da],hop); durdif = hophidur[da] - hoplodur[da]; sumdur = rhopcdur[da]; if (durdif == 0) { dur = sumdur / cnt; warncc(dur > 1440 * 2,Iter,"chop %u dur %u",hop,dur); eqdurs++; } else if (durdif < 10) { dur = sumdur / cnt; warncc(dur > 1440 * 2,Iter,"chop %u dur %u",hop,dur); aeqdurs++; } else { // possible if loop in route hop1 = choporg[hop * 2]; hop2 = choporg[hop * 2 + 1]; infovrb(durdif > 30,Notty|Iter,"chop %u %u-%u dur %u-%u rid %u %s",hop,hop1,hop2,hoplodur[da],hophidur[da],rid,rp->name); dur = hi32; } hopcdur[hop] = dur; hopdur[hop] = min(hopdur[hop],dur); } } // each rid chopcnt = chop; afree(duprids,"cmp duprids"); info(0,"\ah%u compound hops, \ah%u with constant duration, \ah%u within 10 min",chop - hopcnt,eqdurs,aeqdurs); info(0,"avg chain len %u",(ub4)(cumchainlen / chaincnt)); net->chopcnt = chopcnt; net->choporg = choporg; net->hopcdur = hopcdur; // check if distance valid ( minimum 1 unit) #if 1 for (hop = 0; hop < chopcnt; hop++) { dep = portsbyhop[hop * 2]; arr = portsbyhop[hop * 2 + 1]; if (dep == arr) continue; dist = hopdist[hop]; pdep = ports + dep; parr = ports + arr; if (hop < hopcnt) { infocc(dist == 0,0,"hop %u %u-%u \ag%u %s to %s",hop,dep,arr,dist,pdep->name,parr->name); } else { hop1 = choporg[hop * 2]; hop2 = choporg[hop * 2 + 1]; infocc(dist == 0,0,"chop %u = %u-%u %u-%u \ag%u %s to %s",hop,hop1,hop2,dep,arr,dist,pdep->name,parr->name); } } #endif // allocate fare entries here, as they are for both plain and compound hops on reserved routes info(0,"\ah%lu + \ah%lu fare entries for %u hops",cumfevcnt,cumcfevcnt,cumfhops); cumfevcnt += cumcfevcnt; net->fareposcnt = cumfevcnt; ub4 *fhopofs = NULL; if (cumfhops) fhopofs = net->fhopofs = alloc(chopcnt,ub4,0xff,"fare fhopofs",cumfhops); ub4 *ridhops,*ridhopbase = net->ridhopbase; ub4 ofs = 0; ub4 h1ndx,h2ndx,hopndx,rhopcnt,h; for (hop = 0; hop < hopcnt; hop++) { hp = hops + hop; if (hp->reserve) { fhopofs[hop] = ofs; ofs += hp->tp.evcnt; } } for (chop = hopcnt; chop < chopcnt; chop++) { hop1 = choporg[chop * 2]; hop2 = choporg[chop * 2 + 1]; hp = hops + hop1; if (hp->reserve && fhopofs) { fhopofs[chop] = ofs; ofs += hp->tp.evcnt; } rid = hp->rid; rp = routes + rid; rhopcnt = rp->hopcnt; hopndx = 0; h1ndx = h2ndx = hi32; ridhops = ridhopbase + rp->hop2pos; while (hopndx < min(rhopcnt,Chainlen) && (h1ndx == hi32 || h2ndx == hi32)) { h = rp->hops[hopndx]; if (h == hop1) h1ndx = hopndx; else if (h == hop2) h2ndx = hopndx; hopndx++; } if (h1ndx == hi32 || h2ndx == hi32) { vrb0(0,"rid %u hop %u-%u not found at %u-%u chop %u",rid,hop1,hop2,h1ndx,h2ndx,chop); continue; } error_ge(h1ndx,rhopcnt); error_ge(h2ndx,rhopcnt); ridhops[h1ndx * rhopcnt + h2ndx] = chop; } if (cumfhops) net->fareposbase = mkblock(&net->faremem,cumfevcnt * Faregrp,ub2,Init0,"fare entries for %u reserved hops",cumfhops); return 0; }