// before device is removed in response to IRP_MN_REMOVE_DEVICE VOID RoboDeviceEvtDeviceContextCleanup( IN WDFOBJECT Device ) { //PFDO_DATA fdoData; UNREFERENCED_PARAMETER(Device); info0( "RoboDeviceEvtDeviceContextCleanup called\n" ); PAGED_CODE(); return; }
int dorun(ub4 fln,enum Runlvl stage,bool silent) { int run; vrb(0,"dorun stage %u stopat %u",stage, globs.stopat); if (stage >= globs.stopat) run = 0; else if (stage >= Runcnt) run = 1; else run = globs.doruns[stage]; if (silent) return run; info0(User,""); infofln(fln,0,"--- %s stage %u %s ---",run ? "run" : "skip",stage,runlvlnames(stage)); return run; }
// IRP_MN_STOP_DEVICE, IRP_MN_REMOVE_DEVICE NTSTATUS RoboDeviceEvtDeviceReleaseHardware( IN WDFDEVICE Device, IN WDFCMRESLIST ResourcesTranslated ) { //PFDO_DATA fdoData; UNREFERENCED_PARAMETER(Device); UNREFERENCED_PARAMETER(ResourcesTranslated); info0( "RoboDeviceEvtDeviceReleaseHardware called\n" ); PAGED_CODE(); // here - cleanup resources. Unmap memory and I/O ports return STATUS_SUCCESS; }
int prepnet(netbase *basenet) { struct gnetwork *gnet = getgnet(); struct portbase *bports,*bpp; struct subportbase *bsports,*bspp; struct hopbase *bhops,*bhp; struct sidbase *bsids,*bsp; struct chainbase *bchains,*bcp; struct routebase *broutes,*brp; ub8 *bchip,*bchainidxs; struct chainhopbase *bchp,*bchainhops; struct port *ports,*pdep,*parr,*pp; struct sport *sports,*spp; struct hop *hops,*hp; struct sidtable *sids,*sp; struct chain *chains,*cp; struct route *routes,*rp; struct timepatbase *btp; struct timepat *tp; ub4 bportcnt,portcnt; ub4 bsportcnt,sportcnt; ub4 bhopcnt,hopcnt; ub4 dep,arr; ub4 bsidcnt,sidcnt,bchaincnt,chaincnt,chainhopcnt; ub4 bridcnt,ridcnt; ub4 nlen,cnt,acnt,dcnt,sid,rid,rrid; enum txkind kind; ub4 hop,port,sport,chain; ub4 *rrid2rid = basenet->rrid2rid; ub4 hirrid = basenet->hirrid; bhopcnt = basenet->hopcnt; bportcnt = basenet->portcnt; bsportcnt = basenet->subportcnt; bsidcnt = basenet->sidcnt; bridcnt = basenet->ridcnt; bchaincnt = basenet->rawchaincnt; if (bportcnt == 0 || bhopcnt == 0) return error(0,"prepnet: %u ports, %u hops",bportcnt,bhopcnt); // filter but leave placeholder in gnet to make refs match ports = alloc(bportcnt,struct port,0,"ports",bportcnt); portcnt = 0; bports = basenet->ports; for (port = 0; port < bportcnt; port++) { bpp = bports + port; pp = ports + port; nlen = bpp->namelen; if (bpp->ndep == 0 && bpp->narr == 0) { info(0,"skip unconnected port %u %s",port,bpp->name); if (nlen) memcpy(pp->name,bpp->name,nlen); pp->namelen = nlen; continue; } // new ndep,narr filled lateron pp->valid = 1; pp->id = pp->allid = pp->gid = portcnt; pp->cid = bpp->cid; nlen = bpp->namelen; if (nlen) { memcpy(pp->name,bpp->name,nlen); pp->namelen = nlen; } else info(0,"port %u has no name", port); pp->lat = bpp->lat; // error_z(pp->lat,port); pp->lon = bpp->lon; pp->rlat = bpp->rlat; pp->rlon = bpp->rlon; pp->utcofs = bpp->utcofs; pp->modes = bpp->modes; pp->subcnt = bpp->subcnt; pp->subofs = bpp->subofs; portcnt++; } info(0,"%u from %u ports",portcnt,bportcnt); portcnt = bportcnt; sports = alloc(bsportcnt,struct sport,0,"sports",bsportcnt); sportcnt = 0; bsports = basenet->subports; for (sport = 0; sport < bsportcnt; sport++) { bspp = bsports + sport; spp = sports + sport; nlen = bspp->namelen; if (nlen) memcpy(spp->name,bspp->name,nlen); else info(0,"sport %u has no name", sport); spp->namelen = nlen; if (bspp->ndep == 0 && bspp->narr == 0) { vrb0(Notty,"unconnected subport %u %s",sport,bspp->name); // continue; } spp->valid = 1; spp->id = sportcnt; spp->cid = bspp->cid; spp->parent = bspp->parent; spp->lat = bspp->lat; error_z(spp->lat,sport); spp->lon = bspp->lon; spp->rlat = bspp->rlat; spp->rlon = bspp->rlon; spp->modes = bspp->modes; spp->seq = bspp->seq; sportcnt++; } info(0,"%u from %u sports",sportcnt,bsportcnt); sportcnt = bsportcnt; sidcnt = bsidcnt; sids = alloc(sidcnt,struct sidtable,0,"sids",sidcnt); bsids = basenet->sids; for (sid = 0; sid < bsidcnt; sid++) { bsp = bsids + sid; sp = sids + sid; sp->sid = bsp->sid; sp->t0 = bsp->t0; sp->t1 = bsp->t1; nlen = bsp->namelen; if (nlen) { memcpy(sp->name,bsp->name,nlen); sp->namelen = nlen; } } info(0,"%u sids",sidcnt); ub4 cumrhops = 0,cumrhops2 = 0; ub4 ofs = 0; ridcnt = bridcnt; routes = alloc(ridcnt,struct route,0,"routes",ridcnt); broutes = basenet->routes; for (rid = 0; rid < ridcnt; rid++) { brp = broutes + rid; rp = routes + rid; rp->rrid = brp->rrid; rp->kind = brp->kind; rp->reserve = brp->reserve; rp->chainofs = brp->chainofs; rp->chaincnt = brp->chaincnt; cnt = rp->hopcnt = brp->hopcnt; rp->hichainlen = brp->hichainlen; nlen = brp->namelen; if (nlen) { memcpy(rp->name,brp->name,nlen); rp->namelen = nlen; } rp->hop2pos = ofs; ofs += cnt * cnt; } info(0,"%u routes",ridcnt); cumrhops = ofs; block *ridhopmem = &gnet->ridhopmem; gnet->ridhopbase = mkblock(ridhopmem,cumrhops + cumrhops2,ub4,Init1,"net"); ub4 *gportsbyhop = alloc(bhopcnt * 2, ub4,0xff,"net portsbyhop",bhopcnt); ub4 dist,*hopdist = alloc(bhopcnt,ub4,0,"net hopdist",bhopcnt); ub4 midur,*hopdur = alloc(bhopcnt,ub4,0,"net hopdur",bhopcnt); ub4 *drids,*arids,*deps,*arrs; ub4 t0,t1,tdep,prvtdep,evcnt; hops = alloc(bhopcnt,struct hop,0,"hops",bhopcnt); hopcnt = 0; bhops = basenet->hops; for (hop = 0; hop < bhopcnt; hop++) { bhp = bhops + hop; dep = bhp->dep; arr = bhp->arr; error_ge(dep,portcnt); error_ge(arr,portcnt); if (dep == arr) { bpp = bports + dep; warning(0,"nil hop %u %s at %u",dep,bpp->name,bhp->cid); continue; } else if (bhp->valid == 0) { bpp = bports + dep; warning(0,"invalid hop %u %s at %u",dep,bpp->name,bhp->cid); continue; } pdep = ports + dep; parr = ports + arr; error_z(pdep->valid,hop); error_z(parr->valid,hop); gportsbyhop[hop * 2] = dep; gportsbyhop[hop * 2 + 1] = arr; hp = hops + hop; hp->gid = hop; nlen = bhp->namelen; if (nlen) { memcpy(hp->name,bhp->name,nlen); hp->namelen = nlen; } rrid = bhp->rrid; error_gt(rrid,hirrid,hop); hp->rrid = rrid; rid = rrid2rid[rrid]; hp->rid = rid; if (rid != hi32) { rp = routes + rid; hp->reserve = rp->reserve; } else { rp = NULL; hp->reserve = 0; } hp->rhop = bhp->rhop; tp = &hp->tp; btp = &bhp->tp; t0 = btp->t0; t1 = btp->t1; evcnt = btp->evcnt; tp->utcofs = btp->utcofs; tp->tdays = btp->tdays; tp->gt0 = btp->gt0; tp->t0 = t0; tp->t1 = t1; tp->evcnt = evcnt; tp->genevcnt = btp->genevcnt; noexit error_ne(tp->genevcnt,evcnt); // todo tp->genevcnt = min(tp->genevcnt,evcnt); tp->evofs = btp->evofs; tp->dayofs = btp->dayofs; tp->lodur = btp->lodur; tp->hidur = btp->hidur; midur = tp->midur = btp->midur; hopdur[hop] = midur; tp->avgdur = btp->avgdur; tp->duracc = btp->duracc; // mark local links pdep = ports + dep; parr = ports + arr; dcnt = pdep->ndep; deps = pdep->deps; drids = pdep->drids; if (dcnt == 0) { deps[0] = hop; drids[0] = rid; pdep->ndep = 1; } else if (dcnt == 1) { if (deps[0] != hop || drids[0] != rid) { deps[1] = hop; drids[1] = rid; pdep->ndep = 2; } } else if ( (deps[0] == hop && drids[0] == rid) || (deps[1] == hop && drids[1] == rid) ) ; else pdep->ndep = dcnt + 1; acnt = parr->narr; arrs = parr->arrs; arids = parr->arids; if (acnt == 0) { arrs[0] = hop; arids[0] = rid; parr->narr = 1; } else if (acnt == 1) { if (arrs[0] != hop || arids[0] != rid) { arrs[1] = hop; arids[1] = rid; parr->narr = 2; } } else if ( (arrs[0] == hop && arids[0] == rid) || (arrs[1] == hop && arids[1] == rid) ) ; else parr->narr = acnt + 1; kind = bhp->kind; hp->kind = kind; dist = hp->dist = bhp->dist; hopdist[hop] = dist; error_z(dist,hop); hp->dep = dep; hp->arr = arr; hopcnt++; } if (hopcnt == 0) return error(0,"nil hops out of %u",bhopcnt); info(0,"%u from %u hops",hopcnt,bhopcnt); hopcnt = bhopcnt; // prepare <rid,dep,arr> to hop lookup ub4 rhop,rhopovf = 0; for (hop = 0; hop < hopcnt; hop++) { hp = hops + hop; rid = hp->rid; if (rid == hi32) continue; error_ge(rid,ridcnt); rp = routes + rid; rhop = hp->rhop; if (rhop < Chainlen) rp->hops[rhop] = hop; else rhopovf++; } warncc(rhopovf,0,"%u of %u hops exceeding %u chain limit",rhopovf,hopcnt,Chainlen); ub4 *bbox = gnet->bbox; // bbox of connected ports for (port = 0; port < portcnt; port++) { pp = ports + port; if (pp->ndep == 0 && pp->narr == 0) continue; updbbox(pp->lat,pp->lon,bbox,Elemcnt(gnet->bbox)); } info(0,"bbox lat %u - %u = %u",bbox[Minlat],bbox[Maxlat],bbox[Latrng]); info(0,"bbox lon %u - %u = %u",bbox[Minlon],bbox[Maxlon],bbox[Lonrng]); ub4 oneridcnt = 0; ub4 onerid; bool oneroute; ub4 ndep,narr; // mark single-route only ports for (port = 0; port < portcnt; port++) { pp = ports + port; ndep = pp->ndep; narr = pp->narr; drids = pp->drids; arids = pp->arids; arrs = pp->arrs; deps = pp->deps; oneroute = 0; onerid = 0; if (ndep == 0 && narr == 0) continue; else if (ndep > 2 || narr > 2) continue; else if (ndep == 0 && narr == 1 && arids[0] != hi32) { oneroute = 1; pp->onerid = arids[0]; } else if (ndep == 1 && narr == 0 && drids[0] != hi32) { oneroute = 1; pp->onerid = drids[0]; } else if (ndep == 1 && narr == 1 && drids[0] == arids[0] && drids[0] != hi32) { oneroute = 1; pp->onerid = arids[0]; } else if (ndep == 2 && narr == 2 && drids[0] != hi32 && drids[1] != hi32) { if (drids[0] == drids[1] && arids[0] == arids[1] && drids[0] == arids[0]) { oneroute = 1; pp->onerid = arids[0]; } else if (drids[0] == arids[0] && drids[1] == arids[1]) { if (sameroute2a(hops,port,drids,deps,arrs)) { oneroute = 1; pp->onerid = arids[0]; } } else if (drids[0] == arids[1] && drids[1] == arids[0]) { if (sameroute2b(hops,port,drids,deps,arrs)) { oneroute = 1; pp->onerid = arids[0]; } } } if (oneroute) { pp->oneroute = 1; pp->onerid = onerid; oneridcnt++; } } info0(0,"global connectivity"); showconn(ports,portcnt,0); ub4 i,idx,bofs,seq,prvseq,rtid; chains = alloc(bchaincnt,struct chain,0,"chains",bchaincnt); bchains = basenet->chains; bchainhops = basenet->chainhops; bchainidxs = basenet->chainidxs; chaincnt = chainhopcnt = ofs = 0; for (chain = 0; chain < bchaincnt; chain++) { bcp = bchains + chain; cp = chains + chain; cp->rid = bcp->rid; cp->tripno = bcp->tripno; cnt = bcp->hopcnt; if (cnt < 3) { vrb(0,"skip dummy chain %u with %u hop\as",chain,cnt); continue; } cp->hopcnt = cnt; cp->rhopcnt = bcp->rhopcnt; cp->rrid = bcp->rrid; cp->rid = bcp->rid; cp->tid = chain; cp->rtid = bcp->rtid; cp->hopofs = ofs; ofs += cnt; chaincnt++; } chainhopcnt = ofs; info(0,"%u from %u chains with %u hops",chaincnt,bchaincnt,chainhopcnt); chaincnt = bchaincnt; ub4 *tid2rtid = alloc(chaincnt,ub4,0,"chain tid2rtid",chaincnt); struct chainhop *chp,*chainhops = alloc(chainhopcnt,struct chainhop,0,"chain hops",chainhopcnt); // write in sorted order for (chain = 0; chain < chaincnt; chain++) { cp = chains + chain; bcp = bchains + chain; cnt = cp->hopcnt; rtid = cp->rtid; tid2rtid[chain] = rtid; if (cnt < 3) continue; ofs = cp->hopofs; bofs = bcp->hopofs; bchip = bchainidxs + bofs; cp->rhopcnt = bcp->rhopcnt; cp->rhopofs = bcp->rhopofs; seq = prvtdep = 0; for (i = 0; i < cnt; i++) { chp = chainhops + ofs + i; idx = bchip[i] & hi32; error_ge(idx,cnt); bchp = bchainhops + bofs + idx; prvseq = seq; seq = (ub4)(bchip[i] >> 32); hop = bchp->hop; tdep = bchp->tdep; error_le(seq,prvseq); chp->hop = hop; chp->tdep = tdep; noexit error_lt(tdep,prvtdep); // todo day wrap ? prvtdep = tdep; chp->tarr = bchp->tarr; error_lt(chp->tarr,chp->tdep); chp->midur = bchp->midur; } } gnet->portcnt = portcnt; gnet->sportcnt = sportcnt; gnet->hopcnt = hopcnt; gnet->sidcnt = sidcnt; gnet->chaincnt = chaincnt; gnet->ridcnt = ridcnt; gnet->ports = ports; gnet->sports = sports; gnet->hops = hops; gnet->sids = sids; gnet->chains = chains; gnet->routes = routes; gnet->portsbyhop = gportsbyhop; gnet->hopdist = hopdist; gnet->hopdur = hopdur; gnet->chainhops = chainhops; gnet->chainrhops = basenet->chainrhops; gnet->chainrphops = basenet->chainrphops; gnet->chainhopcnt = chainhopcnt; gnet->hirrid = hirrid; gnet->rrid2rid = rrid2rid; gnet->tid2rtid = tid2rtid; gnet->hichainlen = basenet->hichainlen; gnet->eventmem = &basenet->eventmem; gnet->evmapmem = &basenet->evmapmem; gnet->events = basenet->events; gnet->evmaps = basenet->evmaps; gnet->t0 = basenet->t0; gnet->t1 = basenet->t1; gnet->walklimit = m2geo(globs.walklimit); gnet->sumwalklimit = m2geo(globs.sumwalklimit); gnet->walkspeed = m2geo(globs.walkspeed); info(0,"precomputed walk limit set to %u m, summed %u",globs.walklimit,globs.sumwalklimit); // write reference for name lookup if (wrportrefs(basenet)) return 1; // if (condense(gnet)) return 1; not (yet?) 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; }