/* $Header: /server/users/students/chow/mci/netrestoreW/sparcsrc/RCS/rreact.c,v 1.2 1995/07/11 20:16:47 chow Exp chow $ */ /* This program is available for research only. For commercial use, please check * with chow@cs.uccs.edu. */ /* Project : NetRestore Algorithm Name : Rapid REstoration of Active Communications Trunks (RREACT) Programmed by : Steve McCaughey Date : 24 July 1992 Version : 1.0.2 This program models the RREACT digital network restoration algorithm using NETSIM and other library routines. Date - Initials - Description of Modification --------------------------------------------- Revision History: 9/28/92 SCM Modified program for additional output options. (.1) 12/17/92 SCM Modified program for knapsack solution optimizations. (.2) 5/1/93 mjfeuers Port it to C. 6/10/93 chow add transmission delay command line use x as option for transmission delay /x=64 for 64kbps speed (note t is used for timeout) 6/6/94 chow add overwrite link distance option 6/7/94 chow add parallel dcs connection option 7/9/95 chow fix bug in porting from dec to sun */ #include #include /* #include Dr. Chow's method for GetDate in fitness.c */ #include #include #include "strings2.h" #include "netsim.h" #include "lists.h" #include "globals2.h" #include "knapsack2.h" #include "rmath.h" #include "heuropt2.h" extern double sqrt(); Static long maxrepeats = 13; /* to avoid looping */ Static boolean overwriteRL = false; Static long spare_used; Static long rstr_msg_count = 0; Static float lastRestoreTime = 0.0; /* in sec */ Static float connectTime = 0.0; /* in sec */ Static boolean OVERWRITE_LINK_DISTANCE; Static long LINK_DISTANCE_IN_MILES = 0; /* 1 for link distance in miles 2 for link distance in km 0 for link distance field not used */ Static float NOISE_SIZE = 0.00001; /* multiplied by random 0..100 */ Static float PPTOVERRIDE = -1.0; static int PARALLEL_DCS = 0;/*default parallel DCS connection all in one batch*/ /* 1 for connecting one path at CROSS_CONNECT_TIME time */ /* k for connecting k paths at CROSS_CONNECT_TIME time */ Static int TX_SPEED = 8; /* default transmission speed is 8 kbps */ Static float CROSS_CONNECT_TIME = 0.01; /*default DCS connection time 10msec*/ Static float LINK_CHECK_SCALEFACTOR = 0.05; /* fraction of node msg process delay */ Static float TIMEOUT = 0.25; /* sec -- CHOOSER timeout value */ Static float STOP_TIME = 5.0; /* sec -- total run time of simulation */ Static float REFRACINDEX = 1.5; boolean DEBUG = false; static float TRIGGER_TIMEOUT = 0.0300; static float MSG_BYTE_DELAY = 0.001; static char statechar[3] = { ' ', ' ', ' ' }; /*state display-viapath printout*/ /* GetTime and GetDate probably are Turbo Pascal library routines */ /* replace that with the equivalent unix c library */ Void GetTime(hr, min, sec, csec) unsigned short hr, min, sec, csec; { struct timeval t; struct tm *local; /* note that tm_hour tm_min tm_sec are all int type, not short */ gettimeofday(&t, 0); local = localtime((time_t *)&t.tv_sec); hr = local->tm_hour; min = local->tm_min; sec = local->tm_sec; csec = t.tv_usec/10000L; } Void GetDate(yr, mon, day, dow) unsigned short yr, mon, day, dow; { struct timeval t; struct tm *local; gettimeofday(&t, 0); local = localtime((time_t *)&t.tv_sec); yr = local->tm_year; mon = local->tm_mon; day = local->tm_mday; dow = local->tm_wday; } static char *simtime2str(Result, v) char *Result; float v; { char s[256]; sprintf(s, "%8.5f", v); return strcpy(Result, s); } static char *int2str_(Result, i) /* Dr. Chow's int2str function */ char *Result; /* int2str_ is used for BWVEC since each element is 3 digits */ long i; { char s[6]; i %= 1000; sprintf(s, "%03.3ld", i); strcpy(Result, s); return Result; } /* int2str function from Pascal translator */ static char *int2str__(Result, i) char *Result; long i; { char STR1[8]; sprintf(STR1, "%6d", i); strcpy(Result, STR1); return Result; } static float noise() { /* short temp; temp = rand(); return (float)temp * NOISE_SIZE; */ /* modify for non-BSD float n; n = random()*100.0*NOISE_SIZE/(pow((double)2, (double) 32)-1.0); return (n); */ return 0.0; } static Void simlog(s) char *s; { fprintf(log_, "%s\n", s); } Local void listdump(ll, s) list ll; char *s; { long i; char c; pathtuple *xx; long FORLIM; printf("WHERE -> %s\n", s); xx = (pathtuple *)head_list(&ll); while (xx != NULL) { printf("%4ld", xx->id); printf("%8ld", xx->bw); printf("%4ld", xx->hc); printf("%8.4f", xx->wp); printf("%4ld", xx->spares); printf(" ---- "); FORLIM = xx->hc; for (i = 0; i <= FORLIM; i++) printf("%3d", xx->pathvec[i]); putchar('\n'); c = getchar(); /* c = ReadKey(); */ xx = (pathtuple *)next_list(&ll); } putchar('\n'); } Local float transmit_delay(p, double_) char *p; boolean double_; { long hops, ix; hops = strlen(p) / 4; ix = hops; if (double_) ix += hops; /* return (MSG_BYTE_DELAY * (ix + FIXED_BYTE_OVERHEAD)); */ return ( (8.0/(TX_SPEED*1000))* (ix + FIXED_BYTE_OVERHEAD)); } Local long make_path_vector(p, path) char *p; char *path; { long xfer; long i, hops, err; char STR1[256]; char STR2[256]; hops = strlen(p) / 4 - 1; for (i = 0; i <= hops; i++) { if ((DBG_RREACT) && (DBG_MAKE_PATH)) printf("DBG: in make_path_vector: (path or bw) string=%s\n", p); path[i]= (uchar) atoi(strsub(STR1, p, (int)(i * 4 + 1), 3)); } return hops; } Local char find_previous_node(n, path, hops) char n; char *path; long hops; { long test_pos; test_pos = hops; while (test_pos >= 0 && path[test_pos] != n) test_pos--; if (test_pos >= 1) /* found it OK */ return (path[test_pos - 1]); else { printf("%%FP - Previous node on path not found!\n"); exit(0); } } Local char find_next_node(n, path, hops) char n; char *path; long hops; { long test_pos; test_pos = 0; while (test_pos <= hops && path[test_pos] != n) test_pos++; if (test_pos < hops) /* found it OK */ return (path[test_pos + 1]); else { printf("%%FP - Next node on path not found!\n"); exit(0); } } static void process(ev, n, cnode) erec *ev; char n; node *cnode; { char tempstr[256]; char *temp_ptr; long v, err, hops, connect_bw, reject_bw, new_bw, remaining_bw; char previous_node, next_node; long sent; erec *hold; erec *newev; char mtype[256]; linkdata *inlink, *outlink; char pathstr[256]; char bwstr[256]; pathsequence pathvec, bwvec; char *ppathvec, *pbwvec; pathtuple *new_tuple, *temp_tuple, *perm_tuple; list edges, optimal; Anyptr edge; char STR1[256], STR2[256]; char STR3[256]; char FORLIM; char STR4[256]; int anykey; long mindx, maxdx; long updated; float percent; long i, j; if (DEBUG) printf("DBG: in Process, Current_Event: time= %8.5f next=%d src=%d dest=%d\n", ev->time, ev->next, ev->src, ev->dst); /* check for simulation end */ if (ev->time == STOP_TIME) { stop = true; simlog(" "); sprintf(STR2, "Unrestored channels remaining: %s", int2str_(STR1, cnode->tofix)); simlog(STR2); return; } if (DEBUG) { printf("DBG: in Process,(SIM...) cnode->time(Initial)=%8.5f, cnode->msg_proc_delay(Initial)=%8.5f\n", cnode->time, cnode->msg_process_delay); if (cnode->tofix != 0) printf("DBG: in Process, cnode->name=%s has non-zero cnode->tofix=%d\n",cnode->name, cnode->tofix); } /* check for update of node local time */ if (ev->time > cnode->time) cnode->time = ev->time; /* time it takes to process incoming msg */ if (PPTOVERRIDE >= 0.0) cnode->time += PPTOVERRIDE + noise(); else cnode->time += cnode->msg_process_delay + noise(); /* determine msg type */ find_symbol_def(mtype, ev->msg, "TYPE"); /* check if "SIM" control messages */ if (!strcmp(mtype, SIM_MSG)) { find_symbol_def(tempstr, ev->msg, "ACTION"); if (DEBUG) printf("DBG: in Process, (SIM control msg) ev->msg= %s\n", tempstr); if (strcmp(tempstr, "BREAK")) /* return if != BREAK */ return; /* set state & deactivate link */ /* set SEEKER or CONNECTOR */ if (n == break1) { cnode->state = SEEKER; maxrepeats = cnode->repeatlimit; printf("Maximum repeat limit is set to %d\n", maxrepeats); /* deactivate link & set channels to restore */ outlink = (linkdata *)head_list(&cnode->links); if (outlink == NULL) { printf("There is no span from %s to %s\n", break1str, break2str); exit(3); } while (outlink->dest != break2) { outlink = (linkdata *)next_list(&cnode->links); if (outlink == NULL) { printf("There is no span from %s to %s\n", break1str, break2str); exit(3); } } outlink->active = false; cnode->tofix = outlink->work; /* complete screen's header message */ bw_needed = cnode->tofix; printf("(%ld working channels lost)\n\n", bw_needed); /* flood msgs */ /* init common msg fields */ newev = (erec *)malloc(sizeof(erec)); *newev = *ev; newev->msg = NULL; init_symbol(&newev->msg, "TYPE", SEEK_MSG); sprintf(pathstr, "%s%c", int2str_(STR1, (long)n), statechar[(long)cnode->state]); init_symbol(&newev->msg, "PATH", pathstr); /* do flood to "reasonable" nodes */ sent = 0; FORLIM = cnode->links.count; if (DEBUG) printf("DBG: in Process (SIM) cnode->links.count= %d\n", cnode->links.count); for (i = 1; i <= FORLIM; i++) { outlink = (linkdata *)recall_list(&cnode->links, (long)i); if (outlink->active && outlink->spare != 0) { sent++; /* send msg */ /* new msg creation */ hold = (erec *)malloc(sizeof(erec)); *hold = *newev; copy_symbols(&newev->msg, &hold->msg); sprintf(STR2, "%s-", int2str_(STR1, outlink->spare)); if (DEBUG) { printf("DBG: in Process,(SIM...) outlink->spare=%s\n", STR2); printf("DBG: in Process,(SIM...) hold->time=%8.5f\n", hold->time); printf("DBG: in Process,(SIM...) cnode->time=%8.5f\n", cnode->time); printf("DBG: in Process,(SIM...) cnode->msg_proc_delay=%8.5f\n", cnode->msg_process_delay); printf("DBG: in Process,(SIM...) outlink->delay=%8.5f\n", outlink->delay); printf("DBG: in Process,(SIM...) sent=%d\n", sent); } init_symbol(&hold->msg, "BWVEC", STR2); hold->time = cnode->time + sent * cnode->msg_process_delay + transmit_delay(pathstr, true) + outlink->delay + noise(); if (DEBUG) printf("DBG: in Process,(SIM...) hold->time(after calc)=%8.5f\n", hold->time); hold->next = outlink->dest; hold->src = n; if (DEBUG) printf("DBG: in Process,(SIM...) queuing SEEK_MSG for 1 link.\n"); queue_event(hold); } } /* update node time */ cnode->time += sent * cnode->msg_process_delay + i * cnode->msg_process_delay * LINK_CHECK_SCALEFACTOR; return; } if (DEBUG) printf("DBG: in Process (SIM) cnode->state=CONNECTOR \n"); cnode->state = CONNECTOR; /* deactivate link & set channels to restore */ outlink = (linkdata *)head_list(&cnode->links); while (outlink->dest != break1) { outlink = (linkdata *)next_list(&cnode->links); } outlink->active = false; cnode->tofix = outlink->work; /* build capacity array in heap based on netsize */ cnode->capacity = (long(*)[MAXNODES])malloc(sizeof(cap_table)); for (i = 0; i < MAXNODES; i++) { for (j = 1; j <= MAXNODES; j++) cnode->capacity[i][j - 1] = (long)MAXINT; } /* queue event to stop simulation to CONNECTOR */ hold = (erec *)malloc(sizeof(erec)); *hold = *ev; copy_symbols(&ev->msg, &hold->msg); init_symbol(&hold->msg, "TYPE", STOP_MSG); init_symbol(&hold->msg, "PATH", "SIMULATION TIMEOUT"); init_symbol(&hold->msg, "BWVEC", "***"); hold->time = STOP_TIME; hold->next = n; hold->src = NIL_NODE; if (DEBUG) printf("DBG: in Process,(SIM) queueing STOP event to CONNECTOR.\n"); queue_event(hold); return; /* don't need to process normal states */ } /* start of normal message processing... ***************** */ msg_count++; if (cnode->state == IDLE && !strcmp(mtype, SEEK_MSG)) { /* check if viable SEEK msg first. i.e., can be used */ if (cnode->time > STOP_TIME / 2) return; /* flood msgs */ /* init common msg fields */ find_symbol_def(pathstr, ev->msg, "PATH"); find_symbol_def(bwstr, ev->msg, "BWVEC"); sprintf(pathstr + strlen(pathstr), "%s%c", int2str_(STR1, (long)n), statechar[(long)cnode->state]); if (strlen(pathstr)/4 > maxrepeats) return; init_symbol(&ev->msg, "PATH", pathstr); /* do flood to "reasonable" nodes */ sent = 0; FORLIM = cnode->links.count; for (i = 1; i <= FORLIM; i++) { outlink = (linkdata *)recall_list(&cnode->links, (long)i); if ((outlink->active && outlink->spare != 0) & (strpos2(pathstr, int2str_(STR1, (long)outlink->dest), 1) == 0)) { sent++; /* new msg creation */ hold = (erec *)malloc(sizeof(erec)); *hold = *ev; copy_symbols(&ev->msg, &hold->msg); hold->time = cnode->time + sent * cnode->msg_process_delay + transmit_delay(pathstr, true) + outlink->delay + noise(); sprintf(STR4, "%s%s-", bwstr, int2str_(STR2, outlink->spare)); init_symbol(&hold->msg, "BWVEC", STR4); hold->next = outlink->dest; hold->src = n; queue_event(hold); } } /* update node time */ cnode->time += sent * cnode->msg_process_delay + i * cnode->msg_process_delay * LINK_CHECK_SCALEFACTOR; return; } if (cnode->state == IDLE && !strcmp(mtype, CONNECT_MSG)) { err = (sscanf(find_symbol_def(STR1, ev->msg, "BW"), "%ld", &connect_bw) == 0); find_symbol_def(pathstr, ev->msg, "CONNECT-PATH"); /* init common msg fields */ find_symbol_def(tempstr, ev->msg, "PATH"); sprintf(STR4, "%s%s%c", tempstr, int2str_(STR1, (long)n), statechar[(long)cnode->state]); if (strlen(STR4)/4 > maxrepeats) return; init_symbol(&ev->msg, "PATH", STR4); /* find previous node on path... */ v = make_path_vector(pathstr, pathvec); previous_node = find_previous_node(n, pathvec, v); /* find link information */ /* outgoing... */ outlink = (linkdata *)head_list(&cnode->links); while (outlink->dest != previous_node) { outlink = (linkdata *)next_list(&cnode->links); if (outlink == NULL) { /* chow: sanity check, it should not happen */ return; } } if (outlink->spare >= connect_bw) { /* update info & pass on */ outlink->spare -= connect_bw; outlink->work += connect_bw; /* find & update link information */ /* incoming... */ inlink = (linkdata *)head_list(&cnode->links); while (inlink->dest != ev->src) inlink = (linkdata *)next_list(&cnode->links); inlink->spare -= connect_bw; inlink->work += connect_bw; /* new msg creation */ hold = (erec *)malloc(sizeof(erec)); *hold = *ev; copy_symbols(&ev->msg, &hold->msg); hold->time = cnode->time + cnode->msg_process_delay + transmit_delay(pathstr, false) + outlink->delay + noise(); hold->next = previous_node; hold->src = n; queue_event(hold); /* update node time */ cnode->time += cnode->msg_process_delay + noise(); return; } reject_bw = connect_bw - outlink->spare; connect_bw -= reject_bw; outlink->work += outlink->spare; outlink->spare = 0; /* find & update link information */ /* incoming... */ inlink = (linkdata *)head_list(&cnode->links); while (inlink->dest != ev->src) inlink = (linkdata *)next_list(&cnode->links); inlink->spare -= connect_bw; inlink->work += connect_bw; if (connect_bw > 0) { hold = (erec *)malloc(sizeof(erec)); *hold = *ev; copy_symbols(&ev->msg, &hold->msg); init_symbol(&hold->msg, "BW", int2str_(STR1, connect_bw)); hold->time = cnode->time + cnode->msg_process_delay + transmit_delay(pathstr, false) + outlink->delay + noise(); hold->next = previous_node; hold->src = n; queue_event(hold); /* update node time */ cnode->time += cnode->msg_process_delay + noise(); } /* new msg creation */ /* new msg creation */ hold = (erec *)malloc(sizeof(erec)); *hold = *ev; copy_symbols(&ev->msg, &hold->msg); init_symbol(&hold->msg, "TYPE", REJECT_MSG); sprintf(STR4, "%s%c", int2str_(STR1, (long)n), statechar[(long)cnode->state]); init_symbol(&ev->msg, "PATH", STR4); init_symbol(&hold->msg, "BW", int2str_(STR1, reject_bw)); hold->time = cnode->time + cnode->msg_process_delay + transmit_delay(pathstr, false) + inlink->delay + noise(); hold->next = ev->src; hold->src = n; queue_event(hold); /* update node time */ cnode->time += cnode->msg_process_delay + noise(); return; } /* extract essential info from msg */ if (cnode->state == IDLE && !strcmp(mtype, REJECT_MSG)) { err = (sscanf(find_symbol_def(STR1, ev->msg, "BW"), "%ld", &reject_bw) == 0); find_symbol_def(pathstr, ev->msg, "CONNECT-PATH"); /* init common msg fields */ find_symbol_def(tempstr, ev->msg, "PATH"); sprintf(STR2, "%s%s%c", tempstr, int2str_(STR1, (long)n), statechar[(long)cnode->state]); if (strlen(STR2)/4 > maxrepeats) return; init_symbol(&ev->msg, "PATH", STR2); /* find & update link information */ /* incoming... */ inlink = (linkdata *)head_list(&cnode->links); while (inlink->dest != ev->src) inlink = (linkdata *)next_list(&cnode->links); inlink->spare += reject_bw; inlink->work -= reject_bw; /* find next node on path... */ v = make_path_vector(pathstr, pathvec); next_node = find_next_node(n, pathvec, v); /* find link information */ /* outgoing... */ outlink = (linkdata *)head_list(&cnode->links); while (outlink->dest != next_node) outlink = (linkdata *)next_list(&cnode->links); outlink->spare += reject_bw; outlink->work -= reject_bw; /* new msg creation */ hold = (erec *)malloc(sizeof(erec)); *hold = *ev; copy_symbols(&ev->msg, &hold->msg); hold->time = cnode->time + cnode->msg_process_delay + transmit_delay(pathstr, false) + outlink->delay + noise(); hold->next = next_node; hold->src = n; queue_event(hold); /* update node time */ cnode->time += cnode->msg_process_delay + noise(); return; } /* extract essential info from msg */ if (cnode->state == CONNECTOR && !strcmp(mtype, SEEK_MSG) && optmode == NO_OPT) { /* extract essential info from msg */ find_symbol_def(bwstr, ev->msg, "BWVEC"); find_symbol_def(pathstr, ev->msg, "PATH"); sprintf(pathstr + strlen(pathstr), "%s%c", int2str_(STR1, (long)n), statechar[(long)cnode->state]); /* @@@@ add logic to pass on SEEK_MSG if not part of immediate restoration effort */ /* here logic to determine path's BW or reject path */ hops = make_path_vector(pathstr, &pathvec[0]); hops = make_path_vector(bwstr, &bwvec[0]); /* note: bwvec is one less than modified pathvec, equal to number of hops */ for (i = 0; i <= hops; i++) { cnode->capacity[imin((long)pathvec[i], (long)pathvec[i + 1]) - 1] [imax((long)pathvec[i], (long)pathvec[i + 1]) - 1] = imin((long)bwvec[i], cnode->capacity[imin((long)pathvec[i], (long)pathvec[i + 1]) - 1] [imax((long)pathvec[i], (long)pathvec[i + 1]) - 1]); bwvec[i] = cnode->capacity[imin((long)pathvec[i], (long)pathvec[i + 1]) - 1] [imax((long)pathvec[i], (long)pathvec[i + 1]) - 1]; } connect_bw = MAXINT; for (i = 0; i <= hops; i++) connect_bw = imin(connect_bw, (long)bwvec[i]); /*save good path & bw strs to indexed list for possible use */ if (connect_bw > 0) { temp_ptr = (char *)malloc(strlen(pathstr) + 1L); strcpy(temp_ptr, pathstr); add_list(&cnode->paths, (Anyptr)temp_ptr, (long)cnode->paths.count); temp_ptr = (char *)malloc(strlen(bwstr) + 1L); strcpy(temp_ptr, bwstr); add_list(&cnode->bws, (Anyptr)temp_ptr, (long)cnode->bws.count); } sprintf(STR4, "%s%c", int2str_(STR1, (long)n), statechar[(long)cnode->state]); /* init common msg fields */ init_symbol(&ev->msg, "PATH", STR4); /* find link information */ /* incoming... */ inlink = (linkdata *)head_list(&cnode->links); while (inlink->dest != ev->src) inlink = (linkdata *)next_list(&cnode->links); v = imin(inlink->spare, cnode->tofix); if (v >= connect_bw) cnode->nextpath++; connect_bw = imin(connect_bw, v); if (connect_bw <= 0) return; cnode->tofix -= connect_bw; for (i = 0; i <= hops; i++) cnode->capacity[imin((long)pathvec[i], (long)pathvec[i + 1]) - 1] [imax((long)pathvec[i], (long)pathvec[i + 1]) - 1] -= connect_bw; inlink->spare -= connect_bw; inlink->work += connect_bw; /* new msg creation */ hold = (erec *)malloc(sizeof(erec)); *hold = *ev; copy_symbols(&ev->msg, &hold->msg); init_symbol(&hold->msg, "TYPE", CONNECT_MSG); init_symbol(&hold->msg, "BW", int2str_(STR1, connect_bw)); init_symbol(&hold->msg, "BWVEC", "---"); init_symbol(&hold->msg, "CONNECT-PATH", pathstr); hold->time = cnode->time + cnode->msg_process_delay + transmit_delay(pathstr, false) + inlink->delay + noise(); hold->next = ev->src; hold->src = n; queue_event(hold); /* update node time */ cnode->time += cnode->msg_process_delay + noise(); return; } if (cnode->state == CONNECTOR && !strcmp(mtype, SEEK_MSG) && optmode != NO_OPT) { /* extract essential info from msg */ find_symbol_def(bwstr, ev->msg, "BWVEC"); find_symbol_def(pathstr, ev->msg, "PATH"); sprintf(pathstr + strlen(pathstr), "%s%c", int2str_(STR1, (long)n), statechar[(long)cnode->state]); /* first reset timeout for trigger event countdown */ timer_seqnum++; if (DEBUG) printf("DBG: in Process(ANY_OPT), timer_seqnum= %d\n", timer_seqnum); /* new msg creation */ hold = (erec *)malloc(sizeof(erec)); *hold = *ev; copy_symbols(&ev->msg, &hold->msg); init_symbol(&hold->msg, "TYPE", TRIGGER_EVENT); init_symbol(&hold->msg, "T.O.", int2str_(STR1, timer_seqnum)); hold->time = cnode->time + cnode->msg_process_delay + TRIGGER_TIMEOUT + noise(); hold->next = n; hold->src = NIL_NODE; printf("DBG: in Process,queuing Trigger: hold->time= %8.5f\n", hold->time); queue_event(hold); /* update node time */ cnode->time += cnode->msg_process_delay + noise(); /* @@@@ add logic to pass on SEEK_MSG if not part of immediate restoration effort */ /* here logic to determine path's BW or reject path */ hops = make_path_vector(pathstr, pathvec); hops = make_path_vector(bwstr, bwvec); init_list(&edges); /* note: bwvec is one less than modified pathvec, equal to number of hops */ for (i = 0; i <= hops; i++) { mindx = imin((long)pathvec[i], (long)pathvec[i + 1]); maxdx = imax((long)pathvec[i], (long)pathvec[i + 1]); cnode->capacity[mindx - 1][maxdx - 1] = imin((long)bwvec[i], cnode->capacity[mindx - 1][maxdx - 1]); bwvec[i] = cnode->capacity[mindx - 1][maxdx - 1]; add_list(&edges, NULL, (mindx - 1) * MAXNODES + maxdx - 1); add_list(&capacity, (Anyptr)(&cnode->capacity[mindx - 1][maxdx - 1]), (mindx -1) * MAXNODES + maxdx - 1); /* Preceding section improves readability of the following translated code ** segment. ** cnode->capacity[imin((long)pathvec[i], (long)pathvec[i + 1]) - 1] [imax((long)pathvec[i], (long)pathvec[i + 1]) - 1] = imin((long)bwvec[i], cnode->capacity[imin((long)pathvec[i], (long)pathvec[i + 1]) - 1] [imax((long)pathvec[i], (long)pathvec[i + 1]) - 1]); bwvec[i] = cnode->capacity[imin((long)pathvec[i], (long)pathvec[i + 1]) - 1] [imax((long)pathvec[i], (long)pathvec[i + 1]) - 1]; add_list(&edges, NULL, (imin((long)pathvec[i], (long)pathvec[i + 1]) - 1) * MAXNODES + imax((long)pathvec[i], (long)pathvec[i + 1]) - 1); add_list(&capacity, (Anyptr)(&cnode->capacity[imin((long)pathvec[i], (long)pathvec[i + 1]) - 1] [imax((long)pathvec[i], (long)pathvec[i + 1]) - 1]), (imin((long)pathvec[i], (long)pathvec[i + 1]) - 1) * MAXNODES + imax((long)pathvec[i], (long)pathvec[i + 1]) - 1); ** */ /* p2c: rreact.pas, line 1060: * Note: Line breaker spent 1.0 seconds, 5000 tries on line 714 [251] */ } connect_bw = MAXINT; for (i = 0; i <= hops; i++) connect_bw = imin(connect_bw, (long)bwvec[i]); /*save tuple in knapsack for optimization use */ temp_tuple = (pathtuple *) malloc(sizeof(pathtuple)); /* p2c: rreact.pas, line 671: /* p2c: rreact.pas, line 671: Warning: Expected END, found a '(' [227] */ /* ADDED FROM HYBRID (i.e. manual) TRANSLATION */ temp_tuple->id = pathseq; pathseq++; temp_tuple->pathvec = malloc(sizeof(pathsequence)); memcpy(temp_tuple->pathvec, pathvec, sizeof(pathsequence)); temp_tuple->bwvec = malloc(sizeof(pathsequence)); memcpy(temp_tuple->bwvec, bwvec, sizeof(pathsequence)); temp_tuple->hc = hops + 1; temp_tuple->bw = connect_bw; temp_tuple->wp = 0.0; temp_tuple->spares = (hops + 1) * connect_bw; temp_tuple->edges = edges; if (head_list(&temp_tuple->edges) == NULL) printf("DBG: L777 temp_tuple->edges == NULL\n"); if (DEBUG) printf("DBG: Process(~line 779), Add temp_tuple to (temp & perm)store id=%d bw= %d\n", temp_tuple->id, temp_tuple->bw); add_list(&tempstore, (Anyptr)temp_tuple, temp_tuple->id); add_list(&permstore, (Anyptr)temp_tuple, temp_tuple->id); if (DEBUG) printf("DBG: in Process(~line 783), tempstore.count= %d permstore.count= %d\n", tempstore.count, permstore.count); return; } /* ENDIF CONNECTOR SEEK AND NOT NO_OPT */ /* END OF SECTION ADDED FROM HYBRID (i.e. manual) TRANSLATION */ if (cnode->state == CONNECTOR && !strcmp(mtype, TRIGGER_EVENT) && optmode == KNAPSACK_OPT) { err = (sscanf(find_symbol_def(STR1, ev->msg, "T.O."), "%d", &i) == 0); if ((DBG_RREACT) && (DBG_KNAP)) printf("DBG: in Process(KNAPSACK_OPT), i= %d timer_seqnum= %d\n", i, timer_seqnum); if (i < timer_seqnum) return; if ((DBG_RREACT) && (DBG_KNAP)) printf("DBG: Entering Process(knapsack)...calling initialize_knapsack\n"); initialize_knapsack(cnode->tofix, &capacity); printf("DBG: in Process(KNAPSACK_OPT), cnode->name=%s has cnode->tofix=(INITIAL)= %d\n", cnode->name, cnode->tofix); perm_tuple = (pathtuple *)head_list(&permstore); while (perm_tuple != NULL) { temp_tuple = (pathtuple *)head_list(&tempstore); while (temp_tuple != NULL) { if (temp_tuple->id != perm_tuple->id) { new_bw = perm_tuple->bw; if ((DBG_RREACT) && (DBG_KNAP)) printf("DBG: in Process(~line 809), new_bw(also perm_tuple->bw)= %d\n", new_bw); i = 0; if (head_list(&temp_tuple->edges) == NULL) printf("DBG: L813 temp_tuple->edges == NULL\n"); edge = head_list(&temp_tuple->edges); while (edge != NULL) { if (member_list(&perm_tuple->edges, *(long *)edge)) { remaining_bw = cnode->capacity[imin((long)temp_tuple->pathvec[i], (long)temp_tuple->pathvec[i + 1]) - 1] [imax((long)temp_tuple->pathvec[i], (long)temp_tuple->pathvec[i + 1]) - 1] - temp_tuple->bw; printf("DBG: in Process(innermost IF,~line 823), remaining_bw= %2ld perm_tuple->bw=%2ld\n", remaining_bw, perm_tuple->bw); if (remaining_bw < perm_tuple->bw) { new_bw = imin(new_bw, remaining_bw); printf("DBG: in Process(remaining < perm_tuple)~line 826), new_bw(adjusted)= %d\n", new_bw); } } i++; edge = next_list(&temp_tuple->edges); } if (new_bw > 0 && new_bw < perm_tuple->bw) { new_tuple = (pathtuple *) malloc(sizeof(pathtuple)); /* p2c: rreact.pas, line 728: /* p2c: rreact.pas, line 728: Warning: Expected END, found a '(' [227] */ /* SECTION ADDED FROM HYBRID TRANSLATION */ new_tuple->id = perm_tuple->id; new_tuple->pathvec = perm_tuple->pathvec; new_tuple->hc = perm_tuple->hc; new_tuple->bw = new_bw; new_tuple->spares = perm_tuple->hc * new_bw; new_tuple->edges = perm_tuple->edges; printf("DBG: in Process(~line 845), Add to tempstore new_tuple: id=%d bw= %2ld hc=%2ld spares=%2ld pathvec=%s\n", new_tuple->id, new_tuple->bw, new_tuple->hc, new_tuple->spares, new_tuple->pathvec); add_list(&tempstore, (Anyptr)new_tuple, new_tuple->id); printf("DBG: in Process(~line 848), tempstore.count= %d permstore.count= %d\n", tempstore.count, permstore.count); } /* END OF SECTION ADDED FROM HYBRID TRANSLATION */ } temp_tuple = (pathtuple *)next_list(&tempstore); } perm_tuple = (pathtuple *)next_list(&permstore); } kill(&permstore); /* printf("\n%12u path tuples found:\n\n", tempstore.count); */ temp_tuple = (pathtuple *)head_list(&tempstore); /* printf("RPT: temp_tuple->\n (id bw hc spares -- pathvec)\n"); */ while (temp_tuple != NULL) { printf("%4ld", temp_tuple->id); printf("%4ld", temp_tuple->bw); printf("%4ld", temp_tuple->hc); printf("%4ld", temp_tuple->spares); printf(" ---- "); FORLIM = temp_tuple->hc; for (i = 0; i <= FORLIM; i++) printf("%3d", temp_tuple->pathvec[i]); putchar('\n'); add_to_knapsack(&temp_tuple); if ((DBG_RREACT) && (DBG_KNAP)) printf("DBG: count of knapsack = temp_tuple->id=%4ld\n", temp_tuple->id); temp_tuple = (pathtuple *)next_list(&tempstore); } kill(&tempstore); determine_knapsack_solution_components(&optimal); /* printf("\n...working until any key is pressed.\n"); */ /* do { } while (!KeyPressed()); */ /* anykey = getchar(); */ printf("\nOptimal path set found:\n\n"); updated = 0; temp_tuple = (pathtuple *)head_list(&optimal); while (temp_tuple != NULL) { printf("%4ld", temp_tuple->bw); printf("%4ld", temp_tuple->hc); printf("%4ld", temp_tuple->spares); printf(" ---- "); FORLIM = temp_tuple->hc; for (i = 0; i <= FORLIM; i++) printf("%3d", temp_tuple->pathvec[i]); putchar('\n'); *pathstr = '\0'; FORLIM = temp_tuple->hc; for (i = 0; i <= FORLIM; i++) sprintf(pathstr + strlen(pathstr), "%s ", int2str_(STR1, (long)temp_tuple->pathvec[i])); /* new msg creation */ hold = (erec *)malloc(sizeof(erec)); *hold = *ev; copy_symbols(&ev->msg, &hold->msg); init_symbol(&hold->msg, "TYPE", CONNECT_MSG); init_symbol(&hold->msg, "BW", int2str_(STR1, temp_tuple->bw)); init_symbol(&hold->msg, "BWVEC", "---"); init_symbol(&hold->msg, "CONNECT-PATH", pathstr); hold->time = cnode->time + cnode->msg_process_delay + transmit_delay(pathstr, false) + noise(); hold->next = temp_tuple->pathvec[temp_tuple->hc - 1]; hold->src = n; printf("DBG: in Process(KNAPSACK) queuing CONNECT_MSG (bw = %d, via %s\n",temp_tuple->bw, pathstr); queue_event(hold); /* update node time */ cnode->time += cnode->msg_process_delay + noise(); cnode->tofix -= temp_tuple->bw; /* if (!updated) { cnode->tofix -= temp_tuple->bw; updated = 1; } ** TEST CODE */ if ((DBG_RREACT) && (DBG_KNAP)) printf("DBG: in Process(KNAPSACK_OPT), cnode->tofix(UPDATED)= %d\n", cnode->tofix); temp_tuple = (pathtuple *)next_list(&optimal); } putchar('\n'); return; } /*+++*/ if (cnode->state == CONNECTOR && !strcmp(mtype, TRIGGER_EVENT) && optmode == HEURISTIC_OPT) { err = (sscanf(find_symbol_def(STR2, ev->msg, "T.O."), "%d", &i) == 0); if (DEBUG) printf("DBG: in Process(HEURISTIC_OPT), i= %d timer_seqnum= %d\n", i, timer_seqnum); if (i < timer_seqnum) return; /* listdump( permstore, "perm: pre-loop solution"); listdump( tempstore, "temp: pre-loop solution" ); */ determine_heuristic(&permstore, &tempstore, cnode); if (DEBUG) printf("DBG: Returned from 1st Determine_Heuristic call...\n"); /* if ((&permstore)->next->next == NULL) printf("DBG: Returned from 1st Determine_Heuristic call with &permstore->next->next NULL\n"); */ temp_tuple = (pathtuple *)tail_list(&tempstore); while (temp_tuple != NULL && cnode->tofix > 0) { printf("RPT: temp_tuple->\n ( id / bw / hc / wp / spares ---- pathvec)\n"); printf(" %4ld %8ld %4ld %8.4f %4ld ----",temp_tuple->id,temp_tuple->bw,temp_tuple->hc,temp_tuple->wp,temp_tuple->spares); /* printf("%8ld", temp_tuple->bw); printf("%4ld", temp_tuple->hc); printf("%8.4f", temp_tuple->wp); printf("%4ld", temp_tuple->spares); printf(" ---- "); */ FORLIM = temp_tuple->hc; for (i = 0; i <= FORLIM; i++) printf("%3d", temp_tuple->pathvec[i]); putchar('\n'); connect_bw = imin(temp_tuple->bw, cnode->tofix); *pathstr = '\0'; FORLIM = temp_tuple->hc; for (i = 0; i <= FORLIM; i++) sprintf(pathstr + strlen(pathstr), "%s ", int2str_(STR1, (long)temp_tuple->pathvec[i])); sprintf(STR4, "%s%c", int2str_(STR1, (long)n), statechar[(long)cnode->state]); /* init common msg fields */ init_symbol(&ev->msg, "PATH", STR4); /* find link information */ /* incoming... */ inlink = (linkdata *)head_list(&cnode->links); while (inlink->dest != temp_tuple->pathvec[temp_tuple->hc - 1]) inlink = (linkdata *)next_list(&cnode->links); inlink->spare -= connect_bw; inlink->work += connect_bw; cnode->tofix -= connect_bw; FORLIM = temp_tuple->hc; for (i = 0; i < FORLIM; i++) cnode->capacity[imin((long)temp_tuple->pathvec[i], (long)temp_tuple->pathvec[i + 1]) - 1] [imax((long)temp_tuple->pathvec[i], (long)temp_tuple->pathvec[i + 1]) - 1] -= temp_tuple->bw; /* new msg creation */ hold = (erec *)malloc(sizeof(erec)); *hold = *ev; copy_symbols(&ev->msg, &hold->msg); init_symbol(&hold->msg, "TYPE", CONNECT_MSG); init_symbol(&hold->msg, "BW", int2str_(STR1, connect_bw)); init_symbol(&hold->msg, "BWVEC", "---"); init_symbol(&hold->msg, "CONNECT-PATH", pathstr); hold->time = cnode->time + cnode->msg_process_delay + transmit_delay(pathstr, false) + inlink->delay + noise(); hold->next = temp_tuple->pathvec[temp_tuple->hc - 1]; hold->src = n; queue_event(hold); /* update node time */ cnode->time += cnode->msg_process_delay + noise(); /* remove(&permstore, temp_tuple->id); remove(&tempstore, (long)(temp_tuple->wp * 1000.0) + temp_tuple->id);*/ /* Should these be remove or removels?? */ remove_list(&permstore, temp_tuple->id); remove_list(&tempstore, (long)(temp_tuple->wp * 1000.0) + temp_tuple->id); /* if ((&permstore)->next->next == NULL) printf("DBG: Before 2nd call to Determine_Heuristic call with &permstore->next->next NULL\n"); */ determine_heuristic(&permstore, &tempstore, cnode); if (DEBUG) printf("DBG: Returned from Nth Determine_Heuristic call(in loop)...\n"); temp_tuple = (pathtuple *)tail_list(&tempstore); } /* listdump( permstore, "perm: post-loop solution"); listdump( tempstore, "temp: post-loop solution" ); */ putchar('\n'); return; } if (cnode->state == CONNECTOR && !strcmp(mtype, REJECT_MSG)) { err = (sscanf(find_symbol_def(STR4, ev->msg, "BW"), "%ld", &reject_bw) == 0); find_symbol_def(pathstr, ev->msg, "PATH"); sprintf(pathstr + strlen(pathstr), "%s%c", int2str_(STR4, (long)n), statechar[(long)cnode->state]); hops = make_path_vector(pathstr, pathvec); /* add rejected capacity back onto affected links */ for (i = 0; i < hops; i++) cnode->capacity[imin((long)pathvec[i], (long)pathvec[i + 1]) - 1] [imax((long)pathvec[i], (long)pathvec[i + 1]) - 1] += reject_bw; /* find & update link information */ /* incoming... */ inlink = (linkdata *)head_list(&cnode->links); while (inlink->dest != ev->src) inlink = (linkdata *)next_list(&cnode->links); inlink->spare += reject_bw; inlink->work -= reject_bw; cnode->tofix += reject_bw; do { if (cnode->nextpath < cnode->paths.count) { temp_ptr = (char *)recall_list(&cnode->paths, cnode->nextpath); strcpy(pathstr, temp_ptr); temp_ptr = (char *)recall_list(&cnode->bws, cnode->nextpath); strcpy(bwstr, temp_ptr); v = make_path_vector(bwstr, bwvec); /* determine current channel restoration capability of path */ for (i = 0; i <= v; i++) bwvec[i] = cnode->capacity[imin((long)pathvec[i], (long)pathvec[i + 1]) - 1] [imax((long)pathvec[i], (long)pathvec[i + 1]) - 1]; connect_bw = MAXINT; for (i = 0; i <= v; i++) connect_bw = imin(connect_bw, (long)bwvec[i]); sprintf(STR2, "%s%c", int2str_(STR4, (long)n), statechar[(long)cnode->state]); /* init common msg fields */ init_symbol(&ev->msg, "PATH", STR2); err = (sscanf(strsub(STR4, pathstr, (int)(strlen(pathstr) - 7L), 3), "%d", &next_node) == 0); /* find & check link information */ outlink = (linkdata *)head_list(&cnode->links); while (outlink->dest != next_node) outlink = (linkdata *)next_list(&cnode->links); v = imin(outlink->spare, cnode->tofix); if (v >= connect_bw) cnode->nextpath++; connect_bw = imin(connect_bw, v); if (connect_bw > 0) { reject_bw -= connect_bw; outlink->spare -= connect_bw; outlink->work += connect_bw; cnode->tofix -= connect_bw; /* new msg creation */ hold = (erec *)malloc(sizeof(erec)); *hold = *ev; copy_symbols(&ev->msg, &hold->msg); init_symbol(&hold->msg, "TYPE", CONNECT_MSG); init_symbol(&hold->msg, "BW", int2str_(STR4, connect_bw)); init_symbol(&hold->msg, "BWVEC", "---"); init_symbol(&hold->msg, "CONNECT-PATH", pathstr); hold->time = cnode->time + cnode->msg_process_delay + transmit_delay(pathstr, false) + outlink->delay + noise(); hold->next = next_node; hold->src = n; queue_event(hold); /* update node time */ cnode->time += cnode->msg_process_delay + noise(); } } else { /* what if rejected BW & no paths?! */ /* reset of tofix should handle ok! */ reject_bw = 0; } } while (reject_bw != 0 && cnode->tofix != 0); return; } /* extract essential info from msg */ if (cnode->state != SEEKER || strcmp(mtype, CONNECT_MSG)) return; /* extract essential info from msg */ err = (sscanf(find_symbol_def(STR4, ev->msg, "BW"), "%ld", &connect_bw) == 0); find_symbol_def(pathstr, ev->msg, "CONNECT-PATH"); spare_used += connect_bw * (strlen(pathstr) / 4 - 1); /* find & update link information */ /* incoming... */ inlink = (linkdata *)head_list(&cnode->links); while (inlink->dest != ev->src) inlink = (linkdata *)next_list(&cnode->links); inlink->spare -= connect_bw; inlink->work += connect_bw; cnode->tofix -= connect_bw; FORLIM = netsize; for (i = 0; i <= FORLIM; i++) strcpy(pathstr, replace_strs(STR4, pathstr, int2str_(STR2, (long)i), find_symbol_def(STR1, nodename, int2str_(STR3, (long)i)))); /* print screen status line...*/ bw_found = bw_needed - cnode->tofix; percent = bw_found*100.0/bw_needed; printf("Path %2ld (%2d bw) %3.2f%% ", pathcount, connect_bw, percent); if (PARALLEL_DCS == 0) connectTime = CROSS_CONNECT_TIME; else if (connect_bw%PARALLEL_DCS) { connectTime = (connect_bw/PARALLEL_DCS+1)*CROSS_CONNECT_TIME; } else { connectTime = (connect_bw/PARALLEL_DCS)*CROSS_CONNECT_TIME; } if (cnode->time > lastRestoreTime) lastRestoreTime = cnode->time + connectTime; else lastRestoreTime = lastRestoreTime + connectTime; /* connect to be put off */ printf("rstrd@%3.2fmsec ", lastRestoreTime*1000); printf("-->(%s)\n", pathstr); pathcount++; rstr_msg_count = msg_count; /* reject all or part of requested path-bw */ } static void init_nodes(s) char *s; { FILE *netdef; char line[256], tline[256]; char idx, jdx; long err, linkcount; float distance; node *cnode, *idxnode, *jdxnode; linkdata *clink; char STR1[256]; char FORLIM; char *TEMP; char FORLIM1; double TEMP1, TEMP2; char type[20]; long V_Hcoord = 0; float linkdistance; /* get net file ready for read */ netdef = fopen( to_lower(STR1,s), "r"); /* define SIM node, mainly for logging purposes as source */ cnode = (node *)malloc(sizeof(node)); strcpy(cnode->name, "SIM"); init_symbol(&nodename, int2str_(STR1, 0L), cnode->name); if (DEBUG) printf("DBG: in init_nodes, Node/def initialized = %s %s\n", STR1, cnode->name); add_list(&net, (Anyptr)cnode, 0L); fscanf(netdef, "%ld %s%*[^\n]", &netsize, type); if (strcmp(type, "V_H2") == 0) { OVERWRITE_LINK_DISTANCE = true; V_Hcoord = 1; } else if (strcmp(type, "L_L2") == 0) { OVERWRITE_LINK_DISTANCE = true; V_Hcoord = 0; } else if (strcmp(type, "V_H2wSpanMiles") == 0) { LINK_DISTANCE_IN_MILES = 1; V_Hcoord = 1; printf("Overwrite Propagation delay using the span miles specified in each link.\n"); } else if (strcmp(type, "L_L2wSpanKms") == 0) { LINK_DISTANCE_IN_MILES = 2; V_Hcoord = 0; printf("Overwrite Propagation delay using the span km specified in each link.\n"); } else { printf("unrecongized file type=%s\n This program recognizes V_H2, L_L2, V_H2wSpanMiles, and L_L2wSpanKms.\n", type); } getc(netdef); FORLIM = netsize; /* for all nodes ... */ for (idx = 1; idx <= FORLIM; idx++) { cnode = (node *)malloc(sizeof(node)); init_list(&cnode->links); init_list(&cnode->paths); init_list(&cnode->bws); cnode->id = idx; cnode->time = 0.0; cnode->tofix = 0; cnode->nextpath = 0; fgets(line, 256, netdef); if (DEBUG) printf("DBG: in init_nodes, line(node)=\nDBG: %s\n", line); TEMP = strchr(line, '\n'); if (TEMP != NULL) *TEMP = 0; tokenize(tline, line); if (DEBUG) printf("DBG: in init_nodes, tline(node)= %s\n", tline); get_token(cnode->name, tline); if (DEBUG) printf("DBG: in init_nodes, cnode->name= %s\n", cnode->name); init_symbol(&nodename, int2str_(STR1, (long)idx), cnode->name); err = (sscanf(get_token(STR1, tline), "%ld", &linkcount) == 0); err = (sscanf(get_token(STR1, tline), "%g", &cnode->msg_process_delay) == 0 ); cnode->state = 0; /* this field is now used for node specific repeat limit err = (sscanf(get_token(STR1, tline), "%d", (int *)(&cnode->state)) == 0); */ err = (sscanf(get_token(STR1, tline), "%d", &cnode->repeatlimit) == 0); if (overwriteRL) { cnode->repeatlimit = maxrepeats; if (DEBUG) printf("repeat limit of %s is overwritten to %d.\n", cnode->name, cnode->repeatlimit); } else if (cnode->repeatlimit == 0) { cnode->repeatlimit = maxrepeats; if (DEBUG) printf("repeat limit of %s is set to default value %d.\n", cnode->name, cnode->repeatlimit); } else { if (DEBUG) printf("repeat limit of %s is set to %d.\n", cnode->name, cnode->repeatlimit); if (cnode->repeatlimit > maxrepeats) maxrepeats = cnode->repeatlimit; } err = (sscanf(get_token(STR1, tline), "%g", &cnode->lat) == 0); err = (sscanf(get_token(STR1, tline), "%g", &cnode->long_) == 0); /* for all links... */ for (jdx = 1; jdx <= linkcount; jdx++) { clink = (linkdata *)Malloc(sizeof(linkdata)); fgets(line, 256, netdef); TEMP = strchr(line, '\n'); if (TEMP != NULL) *TEMP = 0; tokenize(tline, line); err = (sscanf(get_token(STR1, tline), "%ld", &clink->dest) == 0); clink->active = (strcmp(get_token(STR1, tline), "1") == 0); err = (sscanf(get_token(STR1, tline), "%ld", &clink->work) == 0); err = (sscanf(get_token(STR1, tline), "%ld", &clink->spare) == 0); if (!OVERWRITE_LINK_DISTANCE) { if (LINK_DISTANCE_IN_MILES != 0) err = (sscanf(get_token(STR1, tline), "%f", &linkdistance) == 0); if (err) { clink->delay = 0.0; printf("Error: the net file does not have link distance field\n" ); exit(1); } else { if (LINK_DISTANCE_IN_MILES == 1) { /* linkdistance field in miles, 1 mile = 1.6093km */ clink->delay = (linkdistance*1.6093)/(LIGHTSPEED/REFRACINDEX); } else { /* linkdistance field in km */ clink->delay = linkdistance / (LIGHTSPEED/REFRACINDEX); } if (DEBUG) { printf("linkdistance =%f, LIGHTSPEED=%f, REFRACINDEX=%f\n", linkdistance, LIGHTSPEED, REFRACINDEX); printf("link %d-%d (internalIDs) delay is set to %f seconds.\n", cnode->id, clink->dest, clink->delay); } } } else clink->delay = 0.0; add_list(&cnode->links, (Anyptr)clink, (long)jdx); } add_list(&net, (Anyptr)cnode, (long)idx); } FORLIM = netsize; /* calculate link delays based on relative distances */ for (idx = 1; idx <= FORLIM; idx++) { idxnode = (node *)recall_list(&net, (long)idx); FORLIM1 = idxnode->links.count; for (jdx = 1; jdx <= FORLIM1; jdx++) { clink = (linkdata *)recall_list(&idxnode->links, (long)jdx); if (clink->active) { jdxnode = (node *)recall_list(&net, (long)clink->dest); TEMP1 = idxnode->lat - jdxnode->lat; TEMP2 = idxnode->long_ - jdxnode->long_; if (OVERWRITE_LINK_DISTANCE) { if (V_Hcoord == 1) { distance = sqrt((TEMP2*TEMP2+TEMP1*TEMP1)/10)*1.6; /* from Kershenbaum's Telecom. design text instrution manual */ clink->delay = distance / (LIGHTSPEED / REFRACINDEX); } else if (V_Hcoord == 0) { /* use longitude latitude */ distance = sqrt(TEMP2 * TEMP2 + TEMP1 * TEMP1); clink->delay = distance * KMPERDEG / (LIGHTSPEED / REFRACINDEX); } if (DEBUG) { printf("link %s-%s delay is overwritten/set to %f seconds.\n", cnode->name, jdxnode->name, clink->delay); } } } else clink->delay = 0.0; if (DEBUG) printf("DBG: in rreact.init_nodes ELSE clink->delay=%8.5f\n", clink->delay); } } if (netdef != NULL) fclose(netdef); netdef = NULL; if (netdef != NULL) fclose(netdef); } static Void log_network(header, name) boolean header; Char *name; { char idx, jdx; node *cnode; linkdata *outlink; node *endnode; linkdata *inlink; unsigned short hr, min, sec, csec, yr, mon, day, dow; char STR1[256], STR2[256], STR3[256], STR4[256]; char FORLIM; char STR5[24]; char FORLIM1; char STR6[256]; char STR7[256]; char STR8[94]; char STR9[56]; char *timestr; /* may be unnecessary */ /* dump initial network configuration */ if (header) { /* timestr = asctime(); */ GetTime(&hr, &min, &sec, &csec); GetDate(&yr, &mon, &day, &dow); sprintf(STR4, "Run Date: %s/%s", int2str_(STR1, (long)mon), int2str_(STR2, (long)day)); simlog(STR4); sprintf(STR3, "Run Time: %s:%s", int2str_(STR1, (long)hr), int2str_(STR2, (long)min)); simlog(STR3); } simlog(" "); sprintf(STR2, "NETWORK DESCRIPTION for %s",name); simlog(STR2); simlog(" "); if (header) simlog(" *AT SIMULATION START* "); else simlog(" *AT SIMULATION STOP* "); simlog(" "); FORLIM = netsize; for (idx = 1; idx <= FORLIM; idx++) { cnode = (node *)recall_list(&net, (long)idx); sprintf(STR5, "* FROM: %s", cnode->name); simlog(STR5); FORLIM1 = cnode->links.count; for (jdx = 1; jdx <= FORLIM1; jdx++) { outlink = (linkdata *)recall_list(&cnode->links, (long)jdx); endnode = (node *)recall_list(&net, (long)outlink->dest); inlink = (linkdata *)head_list(&endnode->links); while (inlink->dest != idx) inlink = (linkdata *)next_list(&endnode->links); sprintf(STR6, " TO: %s OUT: %s/%s IN: %s/%s", endnode->name, int2str_(STR2, outlink->work), int2str_(STR1, outlink->spare), int2str_(STR3, inlink->work), int2str_(STR7, inlink->spare)); simlog(STR6); } simlog(" "); } if (!header) /* dump simulation parameters */ return; simlog(" "); simlog(" "); sprintf(STR1, " STOPTIME=%s", simtime2str(STR2, STOP_TIME)); simlog(STR1); sprintf(STR1, " TX_SPEED=%sKbps", int2str(STR2, TX_SPEED)); sprintf(STR1, " LCS=%s", simtime2str(STR2, LINK_CHECK_SCALEFACTOR)); simlog(STR1); sprintf(STR1, " INDEX=%s", simtime2str(STR2, REFRACINDEX)); simlog(STR1); sprintf(STR1, " NOISE=%s", simtime2str(STR2, NOISE_SIZE)); simlog(STR1); sprintf(STR8, " OUT=%s", outfilename); simlog(STR8); simlog(" "); simlog(" "); sprintf(STR9, " BREAK=%s-%s", break1str, break2str); simlog(STR9); simlog(" "); simlog(" "); simlog(" "); simlog("START OF SIMULATION RUN: "); simlog(" "); simlog(" EV-TIME Q-WAIT"); simlog(" "); } main(argc, argv) int argc; char *argv[]; { FILE *fp; char STR1[256]; char STR2[256]; char FORLIM; char STR3[256]; char STR4[256]; char STR5[256]; char STR6[256]; char STR7[256]; char STR8[256], STR9[256]; char STR10[256]; char STRTMP[256]; Char *cp; long opt_bw_found, opt_spare_used; boolean found; _netsim_init(); _lists_init(); break1 = 0; break2 = 0; SaveEvents = false; stop = false; msg_count = 0; spare_used = 0; pathseq = 0; timer_seqnum = 0; init_list(&tempstore); init_list(&permstore); fixed_list(&capacity, (long)(sizeof(long))); options = NULL; init_symbol(&options, "FIRST_PARAM", NOT_FOUND); init_symbol(&options, "STOPTIME=", "10.0"); init_symbol(&options, "TIMEOUT=", "0.25"); init_symbol(&options, "LCS=", "0.05"); init_symbol(&options, "2INDEX=", "1.5"); init_symbol(&options, "NOISE=", "0.00001"); init_symbol(&options, "PPTOVERRIDE=", "-1.0"); init_symbol(&options, "OUT=", "NETSIM.OUT"); init_symbol(&options, "BREAK=", NOT_FOUND); init_symbol(&options, "DEBUG", NOT_FOUND); init_symbol(&options, "X_SPEED=", "8"); init_symbol(&options, "YPARALLEL_DCS=", "0"); init_symbol(&options, "WRITE_LINK=", NOT_FOUND); init_symbol(&options, "CROSS_CONNECT_TIME=", "0.01"); init_symbol(&options, "ALGORITHM_OPT_CHOICE=", "NONE"); init_symbol(&options, "REPEATS=", NOT_FOUND); if ((DBG_RREACT) && (DBG_CLI)) { printf("DBG: in rreact: cmd line argc = %d \n", argc); sprintf(STRTMP, "%s", argv[0]); printf("DBG: CLI, argv[0] = %s \n", STRTMP); sprintf(STRTMP, "%s", argv[1]); printf("DBG: CLI, argv[1] = %s \n", STRTMP); sprintf(STRTMP, "%s", argv[2]); printf("DBG: CLI, argv[2] = %s \n", STRTMP); } *result = '\0'; cli2(result, &options, '/', argc, &argv[0]); /* cli(result, &options, '/'); */ if (*result != '\0') puts(result); find_symbol_def(infilename, options, "FIRST_PARAM"); if (!strcmp(infilename, NOT_FOUND) || strlen(infilename) == 0) { printf("Required net definition filename found on command line!\n"); _Escape(0); } find_symbol_def(result, options, "BREAK="); if (!strcmp(result, NOT_FOUND)) { printf("Required field /BREAK= not found on command line!\n"); _Escape(0); } sprintf(break1str, "%.*s", strpos2(result, "-", 1) - 1, result); strsub(break2str, result, strpos2(result, "-", 1) + 1, strlen(result)); printf("RREACT simulation result...with %s\n", infilename); printf("Break ocurred between node %s and node %s.\n", break1str, break2str); find_symbol_def(result, options, "REPEATS="); if (strcmp(result, NOT_FOUND)) { /* REPEAT LIMIT OVERWRITE option is specified in command line */ overwriteRL = true; idx = (sscanf(find_symbol_def(STR2, options, "REPEATS="), "%d", &maxrepeats) == 0); printf("MAXREPEATS (longest explored signature path length) set to %d\n", maxrepeats); } /* printf("RPT: Segment for processing command line complete.\n"); */ find_symbol_def(result, options, "WRITE_LINK"); if (!strcmp(result, NOT_FOUND)) { printf("Propagation delay is calculated using link distance specified in net file\n or using node location when link distance field not present.\n"); OVERWRITE_LINK_DISTANCE = false; } else { OVERWRITE_LINK_DISTANCE = true; printf("Propagation delay is calculated using distance between nodes\n"); } find_symbol_def(result, options, "DEBUG"); if (!strcmp(result, NOT_FOUND)) { printf("DEBUG is set to false\n"); } else { DEBUG = true; printf("DEBUG mode is turned on\n"); } find_symbol_def(result, options, "ALGORITHM_OPT_CHOICE="); if (DEBUG) printf("DBG: in rreact, ALGORITHM_OPT_CHOICE, result= %s\n", result); switch (result[0]) { case 'N': optmode = NO_OPT; break; case 'K': optmode = KNAPSACK_OPT; break; case 'H': optmode = HEURISTIC_OPT; break; } idx = (sscanf(find_symbol_def(STR2, options, "2INDEX="), "%g", &REFRACINDEX) == 0); printf("Refraction Index is set at %f.\n", REFRACINDEX); idx = (sscanf(find_symbol_def(STR2, options, "PPTOVERRIDE="), "%g", &PPTOVERRIDE) == 0); if (PPTOVERRIDE != -1.0) printf("Protocol/Message processing time is overwritten/set to %f.\n", PPTOVERRIDE); idx = (sscanf(find_symbol_def(result, options, "X_SPEED="), "%d", &TX_SPEED) == 0); printf("Transmission speed is set at %dKbps\n", TX_SPEED); idx = (sscanf(find_symbol_def(STR2, options, "CROSS_CONNECT_TIME="), "%g", &CROSS_CONNECT_TIME) == 0); printf("CROSS_CONNECT_TIME is set to %g sec.\n", CROSS_CONNECT_TIME); idx = (sscanf(find_symbol_def(result, options, "YPARALLEL_DCS="), "%d", &PARALLEL_DCS) == 0); if (PARALLEL_DCS == 0) printf("DCS is set to connect all found spare paths in %3.2f msec.\n", CROSS_CONNECT_TIME*1000); else if (PARALLEL_DCS == 1) printf("DCS is set to connect one spare path at a time in %3.2f msec.\n", CROSS_CONNECT_TIME*1000); else printf("DCS is set to connect %d spare path at in %3.2f msec.\n", PARALLEL_DCS, CROSS_CONNECT_TIME*1000); idx = (sscanf(find_symbol_def(STR2, options, "NOISE="), "%g", &NOISE_SIZE) == 0); idx = (sscanf(find_symbol_def(STR2, options, "STOPTIME="), "%g", &STOP_TIME) == 0); idx = (sscanf(find_symbol_def(STR2, options, "LCS="), "%g", &LINK_CHECK_SCALEFACTOR) == 0); find_symbol_def(outfilename, options, "OUT="); find_symbol_def(infilename, options, "FIRST_PARAM"); log_ = fopen(outfilename, "w"); if (log_ != NULL) rewind(log_); else log_ = tmpfile(); if (log_ == NULL) _EscIO(FileNotFound); nodename = NULL; if (SaveEvents) set_save_mode(); pathcount = 1; init_list(&net); init_nodes(infilename); FORLIM = netsize; for (i = 1; i <= FORLIM; i++) { find_symbol_def(result, nodename, int2str_(STR1, (long)i)); if (DEBUG) printf("DBG: in rreact, i= %d result= %s STR1= %s\n", i, result, STR1); if (!strcmp(result, break1str)) break1 = i; if (!strcmp(result, break2str)) break2 = i; /* NOTE: this should be changed to exit when break1 & break 2 are found */ } if (break1 == 0) { printf("such such node %s in node1 of the break!\n", break1str); exit(2); } if (break2 == 0) { printf("such such node %s in node2 of the break!\n", break2str); exit(2); } log_network(true, argv[1]); ee = (erec *)malloc(sizeof(erec)); ee->time = 0.0; ee->src = 0; ee->dst = break2; ee->next = break2; ee->msg = NULL; /* init_symbol(&ee->msg, "ID", int2str_(STR1, (long)break1)); */ init_symbol(&ee->msg, "ACTION", "BREAK"); init_symbol(&ee->msg, "TYPE", " SIM"); init_symbol(&ee->msg, "BWVEC", "---"); init_symbol(&ee->msg, "BW", "***"); init_symbol(&ee->msg, "PATH", "INTERNAL FAULT DETECTION"); queue_event(ee); if (DEBUG) printf("DBG: in rreact, 1st Event: break2= %d ee->next= %d\n", break2, ee->next); ee = (erec *)malloc(sizeof(erec)); ee->time = 0.0; ee->src = 0; ee->dst = break1; ee->next = break1; ee->msg = NULL; /* init_symbol(&ee->msg, "ID", int2str_(STR1, (long)break2)); */ init_symbol(&ee->msg, "ACTION", "BREAK"); init_symbol(&ee->msg, "TYPE", " SIM"); init_symbol(&ee->msg, "BWVEC", "---"); init_symbol(&ee->msg, "BW", "***"); init_symbol(&ee->msg, "PATH", "INTERNAL FAULT DETECTION"); queue_event(ee); if (DEBUG) printf("DBG: in rreact, 2nd Event: break1= %d ee->next= %d\n", break1, ee->next); /* printf("RPT: Segment for queuing Break events complete.\n"); */ do { ee = next_event(); if (ee != NULL) { nextnode = (node *)recall_list(&net, (long)ee->next); /* extract path info */ find_symbol_def(printstr, ee->msg, "PATH"); FORLIM = netsize; for (i = 0; i <= FORLIM; i++) strcpy(printstr, replace_strs(STR2, printstr, int2str_(STR1, (long)i), find_symbol_def(STR3, nodename, int2str_(STR4, (long)i)))); if (DEBUG) printf("DBG: in rreact (decoding events) printstr = %s\n", printstr); if (ee->next == break1 || ee->next == break2) { /* print event info */ if (DEBUG) printf("DBG: in rreact,(IF verbose...) ee->next= %d nextnode->time=%8.5f\n", ee->next, nextnode->time); sprintf(STR10, "%s %s %s -> %s of Type: %s with BW: %s", simtime2str(STR2, ee->time), simtime2str(STR3, bounds(0.0, nextnode->time - ee->time, 1.0e30)), find_symbol_def(STR4, nodename, int2str_(STR5, (long)ee->src)), find_symbol_def(STR6, nodename, int2str_(STR7, (long)ee->next)), find_symbol_def(STR8, ee->msg, "TYPE"), find_symbol_def(STR9, ee->msg, "BW")); simlog(STR10); sprintf(STR1, " by %s", printstr); /* extract & print path */ simlog(STR1); /* extract & print path's bw data */ find_symbol_def(printstr, ee->msg, "BWVEC"); sprintf(STR1, " with %s", printstr); simlog(STR1); } /* do event processing at node */ if (DEBUG) printf("DBG: in rreact (calling process)) ee->next= %d\n", ee->next); process(ee, ee->next, nextnode); if (!SaveEvents) { /* release dynamic memeory */ release_all_symbols(&ee->msg); free(ee); } } else stop = true; } while (!(ee == NULL || stop)); to_lower(STR2, infilename); cp = STR2; while (*cp != '.' && cp < STR2 + strlen(STR2)) cp++; *cp = '\0'; /* got the prefix */ sprintf(STR3, "%s.dat.ls/%s_%scut.l", STR2, break1str, break2str); if (access(STR3, R_OK) == 0) { printf("access file %s\n", STR3); found = true; } else { sprintf(STR3, "%s.dat.ls/%s_%scut.l", STR2, break2str, break1str); printf("access file %s\n", STR3); if (access(STR3, R_OK) == 0) { found = true; } else { found = false; printf("optimal spare usage file not found\n"); } } if (found) { fp = fopen(STR3, "r"); while (fgets(STR4, 255, fp)!=NULL) { sscanf(STR4, "%s", STR5); STR5[24]='\0'; if (strcmp(STR5, "TOTAL_BANDWIDTH_RESTORED") == 0) { sscanf(STR5+25, "%d", &opt_bw_found); printf("optimal bandwidth that can be restored=%d\n", opt_bw_found); fgets(STR4, 255, fp); sscanf(STR4, "%s %d", STR5, &opt_spare_used); printf("optimal spare used =%d\n", opt_spare_used); break; } } sprintf(STR1, "%s-%s %d/%d=%6.2f%% @%f msgs=%d/%d PNE=%d/%d PLE=%d/%d\n", break1str, break2str, bw_found, bw_needed, bw_found*100.0/bw_needed, lastRestoreTime, rstr_msg_count, msg_count, bw_found, opt_bw_found, opt_spare_used, spare_used); } else { sprintf(STR1, "%s-%s %d/%d=%6.2f%% @%f msgs=%d/%d spares=%d\n", break1str, break2str, bw_found, bw_needed, bw_found*100.0/bw_needed, lastRestoreTime, rstr_msg_count, msg_count, spare_used); } if (stop) { printf("Unrestored channels = %ld\n", nextnode->tofix); printf("%s", STR1); fprintf(stderr, "%s", STR1); fp = fopen("netres.rr.res", "a"); if (fp == NULL) { fprintf(stderr, "can not open netres.rr.res\n"); } fprintf(fp, "%s", STR1); } fflush(log_); P_ioresult = 0; if (log_ != NULL) fclose(log_); log_ = NULL; exit(0); } /* End. */