Log In
New Account
  
 
Home My Page Project Tree Code Snippets Project Openings NUTSS
 
 
Summary Tracker Lists CVS Files
 

CVS | Administration

Annotation of libnutss/examples/slinks_variable_load.c, revision 1.32

1.24      ths         1: #include <stdio.h>
                      2: #include <stdlib.h>
                      3: #include <string.h>
1.27      ths         4: #include <time.h>
1.28      ths         5: #include <math.h>
                      6: #include <limits.h>
1.24      ths         7: #ifndef WIN32
                      8: #include <poll.h>
                      9: #include <sys/socket.h>
                     10: #endif
                     11: #include <pthread.h>
                     12: #include "../include/swaplinks.h"
                     13:
                     14: #ifdef WIN32
                     15: #define sleep(sec) Sleep((sec)*1000)
                     16: #define snprintf   _snprintf
                     17: #endif
                     18: #define clear(a) a[0]=0
                     19: #define streq(a,b) !strcmp((a),(b))
                     20: #define strlenn(s) (s) ? strlen(s) : 0
                     21: #define randint(N) ((int)(rand() / (((double)RAND_MAX + 1) / (N))))
1.28      ths        22: #define round(f) (f)-(int)(f) > 0.5 ? (int)(f)+1 : (int)(f)
                     23: #define min(a,b) ((a)<(b)?(a):(b))
                     24: #define max(a,b) ((a)>(b)?(a):(b))
1.24      ths        25: #define assert(p) if(!(p)) { printf("Assertion '%s' FAILED!\n", #p); exit(1); }
1.28      ths        26: #define REDUNDANCY    5       // how many message repetitions are necessary to reach every node
                     27: #define PROPAGATION   600     // how many seconds the coordinator should wait for every node to recieve KILL signal
                     28: #define EXPIRATION    600     // how many seconds a node should keep a peering report fron another node
1.29      ths        29: #define MIN_GRACE     1       // minimum number if times a request can be passed on by a full-capacity node
1.31      ths        30: #define MAX_GRACE     60      // maximum
1.28      ths        31: #define ALLOTMENT     400     // how much load a node will accomadate for each of his neighbors (obsolete w/ auto peering)
                     32: #define QUORUM        12      // how many reports a node needs before adjusting his peering level
                     33: #define THRESHOLD     0.15    // how much different a newly calculated degree must be from the old one to switch to it
1.30      ths        34: #define ASSURANCE     0.6     // how sure we want to be that we will find the available capacity out there (affects walk length)
1.28      ths        35: #define MAX_REPORTS   30
                     36: #define WALK_LENGTH   10
1.29      ths        37: #define MIN_PEERS     4
1.30      ths        38: #define MAX_PEERS     25
1.28      ths        39: #define DEFAULT_PEERS 8       // obsolete w/ auto peering
                     40: #define MAX_FLOWS     256
                     41: #define BUFFER_SIZE   128
                     42: #define URI_LENGTH    256
1.24      ths        43:
                     44: typedef struct flow {
1.29      ths        45:     int id, duration, weight, exts, capacity, available, degree;
1.27      ths        46:     char source[URI_LENGTH];
1.24      ths        47:     struct flow *next, *last;
                     48: } flow_t;
                     49:
1.29      ths        50: typedef struct int_pair_t { int i, o; }                                     int_pair;
                     51: typedef struct flw_spec_t { int weight, expiration; }                       flw_spec;
                     52: typedef struct nbr_rprt_t { int expiration, capacity, available, degree; }  nbr_rprt;
1.24      ths        53:
                     54: int_pair process_neighbor_list(char*);
                     55:
1.29      ths        56: // Gobal information, used by both threads
                     57: int num, weight, exts, nodes = 0, peers = 0, capacity = 0, load = 0, alive = 1;
1.24      ths        58: swaplinks_p swp;
1.29      ths        59: FILE *f = NULL, *s = NULL, *q = NULL, *r = NULL;
1.24      ths        60:
1.27      ths        61: // Node's receiving thread that decides whether to accept an incoming
1.28      ths        62: // request and records all the necessary information; also carries
                     63: // out the gossiping-equilibrium protocol to assign peering level
1.27      ths        64: void *recvthread(void *arg) {
1.26      ths        65:     struct sockaddr_ns peer;
                     66:     socklen_t len = sizeof(peer);
1.27      ths        67:     char msg[BUFFER_SIZE], tmp[BUFFER_SIZE];
1.29      ths        68:     int bytes, msg_count, i;
1.27      ths        69:     time_t start,now;
                     70:     flow_t newflow;
1.28      ths        71:     flw_spec flows[MAX_FLOWS];
                     72:     nbr_rprt reports[MAX_FLOWS];
                     73:     nbr_rprt tempbuf[MAX_FLOWS];
                     74:     nbr_rprt sorted[MAX_FLOWS];
                     75:
                     76:     memset(flows,0,sizeof(flw_spec)*MAX_FLOWS);
                     77:     memset(reports,0,sizeof(nbr_rprt)*MAX_FLOWS);
1.26      ths        78:
1.27      ths        79:     start = time(NULL);
                     80:     for(;;) {
1.24      ths        81:         memset(&peer,0,sizeof(peer));
1.28      ths        82:         sleep(1);
1.29      ths        83:     // simulate churn by having a small portion of nodes duck out early, and replace them periodically
1.28      ths        84: //        if(randint(1000) < 2) {
                     85: //            printf("%d Withdrawing from cloud early\n",num);
                     86: //            break;
                     87: //        }
1.29      ths        88:     if((bytes=swaplinks_recvfrom(swp, msg, sizeof(msg), 0, &peer, &len)) > 0) {
1.27      ths        89:             msg[bytes] = 0;
1.28      ths        90:             memcpy(tmp,msg,bytes);
1.27      ths        91:             // Flood SHUTDOWN to neighbors, then power down
                     92:             if(streq(msg,"SHUTDOWN")) {
1.25      ths        93:                 swaplinks_update_walk_length(swp,1);
1.27      ths        94:                 for(i = 0; i < peers*2; i++) swaplinks_sendtoany(swp,"SHUTDOWN",9,0);
                     95:                 printf("%d Recieved KILL signal...\n",num);
1.25      ths        96:                 break;
                     97:             }
1.27      ths        98:             // parse the new flow
                     99:             memcpy(tmp,msg,sizeof(tmp));
                    100:             newflow.duration = atoi(strtok(tmp,";"));
                    101:             newflow.weight = atoi(strtok(NULL,";"));
                    102:             newflow.exts = atoi(strtok(NULL,";"));
1.28      ths       103:             newflow.id = atoi(strtok(NULL,";"));
                    104:             newflow.capacity = atoi(strtok(NULL,";"));
1.29      ths       105:             newflow.available = atoi(strtok(NULL,";"));
                    106:             newflow.degree = atoi(strtok(NULL,";"));
1.27      ths       107:             strncpy(newflow.source,peer.user+4,sizeof(newflow.source));
                    108:
1.28      ths       109:             /*******/
                    110:             // Adjust peering level based on updated picture of the state of the network
                    111:             {
1.29      ths       112:                 int alive = 0, livelinks = 0, totallinks = 0, more = 0, max_capacity = 0, min_capacity = INT_MAX, numReports = 0, src, curmax, k;
                    113:                 float rank, live, newDegree, tempfloat;
1.28      ths       114:                 // parse report
                    115:                 now = difftime(time(NULL),start);
                    116:                 src = atoi(newflow.source);
                    117:                 assert(src < MAX_FLOWS);
                    118:                 // retire any old data and count current reports
                    119:                 for(i=0;i<MAX_FLOWS;i++) {
                    120:                     if(0 < reports[i].expiration && reports[i].expiration > now)
                    121:                         numReports++;
                    122:                     if(0 < reports[i].expiration && reports[i].expiration < now)
                    123:                         memset(reports+i,0,sizeof(nbr_rprt));
                    124:                 }
                    125:                 // dont add this report if we have enough already
                    126:                 if(numReports < MAX_REPORTS) {
                    127:                     reports[src].capacity = newflow.capacity;
1.29      ths       128:                     reports[src].available = newflow.available;
                    129:                     reports[src].degree = newflow.degree;
1.28      ths       130:                     reports[src].expiration = now+EXPIRATION;
                    131:                 }
                    132:                 // gather important data based on known info
                    133:                 for(i=0;i<MAX_FLOWS;i++) {
1.29      ths       134:                     if(0 < reports[i].capacity) {
                    135:                         alive++;
                    136:                         totallinks += reports[i].degree;
                    137:                         if(weight < reports[i].available) livelinks += reports[i].degree;
                    138:                         if(max_capacity < reports[i].capacity) max_capacity = reports[i].capacity;
                    139:                         if(min_capacity > reports[i].capacity && 0 < reports[i].capacity) min_capacity = reports[i].capacity;
                    140:                         if(capacity < reports[i].capacity) more++;
                    141:                     }
1.28      ths       142:                 }
                    143:                 // include this node's capacity in mix
                    144:                 if(max_capacity < capacity) max_capacity = capacity;
                    145:                 if(min_capacity > capacity) min_capacity = capacity;
                    146:                 assert(alive > 0);
1.29      ths       147:                 rank = (float)(alive-more)/alive;
                    148:                 live = (float)livelinks/totallinks;
                    149:                 tempfloat = min(log(1-ASSURANCE)/log(1-live),MAX_GRACE);
                    150:                 if(alive > QUORUM && abs(max(tempfloat,MIN_GRACE)-exts) > exts*THRESHOLD)
                    151:                     exts = round(max(tempfloat,MIN_GRACE));
1.28      ths       152:                 // sort information for viewing purposes
                    153:     //                memcpy(tempbuf,reports,MAX_FLOWS*sizeof(nbr_rprt));
                    154:     //                for(i=0;i<alive;i++) {
                    155:     //                    curmax = 0;
                    156:     //                    for(k=0;k<MAX_FLOWS;k++) {
                    157:     //                        if(tempbuf[curmax].capacity < tempbuf[k].capacity)
                    158:     //                            curmax = k;
                    159:     //                    }
                    160:     //                    sorted[i] = tempbuf[curmax];
                    161:     //                    tempbuf[curmax].capacity = 0;
                    162:     //                }
                    163:
                    164:                 // compute new degree... still need to think about compressing scale if it gets too big
                    165:                 newDegree = rank*min(((float)max_capacity/min_capacity)*MIN_PEERS,MAX_PEERS);
                    166:                 // only alter degree if we have a quorum and the change would be significant
1.29      ths       167:                 if(alive > QUORUM && abs(max(newDegree,MIN_PEERS)-peers) > peers*THRESHOLD) {
1.28      ths       168:                     peers = round(max(newDegree,MIN_PEERS));
1.29      ths       169:                     swaplinks_update_degree(swp,peers);
                    170:                 }
1.28      ths       171:                 if(q) fprintf(q,"%ld %d\n",now,peers);
1.29      ths       172:                 if(r) fprintf(r,"%ld %d\n",now,exts);
1.28      ths       173:
                    174:                 //                printf("- *%d* -\n",capacity);
                    175:                 //                for(i=0;i<alive;i++)
                    176:                 //                    printf(" %d:%4.2f",sorted[i].capacity,(double)(sorted[i].expiration)-difftime(time(NULL),start));
                    177:                 //                printf("\n  %d peering at %d, %4.2f out of %d, adjmax %3.1f\n",num,peers,rank*100.0,alive+1,adjusted_max_peers);
                    178:                 //                printf("---------\n");
                    179:             }
                    180:             /********/
                    181:
1.29      ths       182:             //if(s) fprintf(s,"    %d recvd request %d from %s - w:%d d:%d e:%d\n",
                    183:             //              num,newflow.id,newflow.source,newflow.weight,newflow.duration,newflow.exts);
1.27      ths       184:             // retire any expired flows before processing
                    185:             now = difftime(time(NULL),start);
1.28      ths       186:             for(i=0;i<MAX_FLOWS;i++) {
1.27      ths       187:                 if(0 < flows[i].expiration && flows[i].expiration < now) {
                    188:                     load -= flows[i].weight;
                    189:                     flows[i].weight = 0;
                    190:                     flows[i].expiration = 0;
1.29      ths       191:                     //if(s) fprintf(s,"        %d finished accomodating flow at %ld: %d\n",num,now,load);
1.27      ths       192:                 }
                    193:             }
                    194:             if(load+newflow.weight < capacity) {
                    195:                 load += newflow.weight;
1.28      ths       196:                 // find an empty spot to record this flow
                    197:                 for(i=0;i<MAX_FLOWS;i++) {
1.27      ths       198:                     if(flows[i].expiration == 0) {
                    199:                         flows[i].weight = newflow.weight;
                    200:                         flows[i].expiration = now + newflow.duration;
1.29      ths       201:                         //if(s) fprintf(s,"        %d accepted request at %ld: %d\n",num,now,load);
1.27      ths       202:                         if(f) fprintf(f,"%ld %s\n",now,msg);
                    203:                         break;
1.24      ths       204:                     }
                    205:                 }
1.28      ths       206:                 // if we run out of space, i dont want to add more space, just die.
1.27      ths       207:                 assert(i != MAX_FLOWS);
1.24      ths       208:             }
                    209:             // ADMISSION CONTROL
1.27      ths       210:             // do not accept the flow if it will overload this node.
                    211:             // if the request been pushed too far, reject it, otherwise
                    212:             // pass it on to a neighbor
1.29      ths       213:             else if(newflow.exts > 0) {
1.24      ths       214:                 swaplinks_update_walk_length(swp,1);
1.29      ths       215:                 snprintf(tmp,sizeof(tmp),"%d;%d;%d;%d;%d;%d;%d;",newflow.duration,
                    216:                                                                  newflow.weight,
                    217:                                                                  newflow.exts-1,
                    218:                                                                  newflow.id,
                    219:                                                                  newflow.capacity,
                    220:                                                                  newflow.available,
                    221:                                                                  newflow.degree);
1.27      ths       222:                 swaplinks_sendtoany(swp,tmp,strlenn(tmp)+1,0);
                    223:                 swaplinks_update_walk_length(swp,WALK_LENGTH);
1.29      ths       224:                 if(s) fprintf(s,"  %d rejected flow %d:%d, load too high: %d <= %d\n",num,newflow.id,newflow.exts,capacity,load+newflow.weight);
                    225:                 if(s) fprintf(s,"  %d sends requests with exts: %d\n",num,exts);
1.27      ths       226:                 if(f) fprintf(f,"%ld %s\n",now,"reject");
                    227:             }
                    228:             else {
1.28      ths       229:                 if(s) fprintf(s,"        %d retired unserviceable request %d\n",num,newflow.id);
1.27      ths       230:                 if(f) fprintf(f,"%ld %s\n",now,"retire");
1.24      ths       231:             }
                    232:         }
                    233:     }
1.27      ths       234:     // close output files to assure data is recorded
1.26      ths       235:     if(f && f != stderr) { fclose(f); f = NULL; }
                    236:     if(s && s != stdout) { fclose(s); s = NULL; }
1.25      ths       237:
1.28      ths       238:     alive = 0;
                    239:
1.24      ths       240:     pthread_exit(NULL);
                    241: }
                    242:
                    243: int main(int argc, char **argv) {
                    244:     struct sockaddr_ns reg;
1.27      ths       245:     char tmp[BUFFER_SIZE], nbrs[4096];
1.29      ths       246:     int time = 0, duration, percent, limit, i;
1.27      ths       247:     FILE *g;
1.24      ths       248:     int_pair p;
1.27      ths       249:     pthread_t tid;
1.24      ths       250:
1.27      ths       251:     // parse args
1.24      ths       252:     if(argc > 1) num = atoi(argv[1]);
1.27      ths       253:     if(num != 99 && argc > 6) {
1.28      ths       254:         limit = atoi(argv[2]);
                    255:         percent = atoi(argv[3]);
                    256:         duration = atoi(argv[4]);
                    257:         weight = atoi(argv[5]);
                    258:         capacity = atoi(argv[6]);
                    259:         peers = DEFAULT_PEERS;
1.24      ths       260:     }
1.25      ths       261:     else if(num == 99 && argc > 4) {
1.27      ths       262:         nodes = atoi(argv[2]);
                    263:         // peer coordinator with more nodes
                    264:         // to facilitate dispersion of kill signals
                    265:         peers = atoi(argv[3]);
                    266:         time = atoi(argv[4]);
1.25      ths       267:     }
1.24      ths       268:     else if(num != 99) {
1.28      ths       269:         printf("Usage:\n  slinksvariableload node_number num_messages percent_load flow_duration flow_weight capacity\n");
1.24      ths       270:         exit(1);
                    271:     }
1.25      ths       272:     else {
1.27      ths       273:        printf("Coordinator Usage:\n  slinksvariableload 99 num_nodes num_peers experiment_duration_minutes\n");
1.25      ths       274:        exit(1);
                    275:     }
1.24      ths       276:
1.27      ths       277:     // set all the important nutss fields
1.24      ths       278:     snprintf(tmp, sizeof(tmp), "test%d", num);
                    279:     nutss_config_set(NUTSS_CONFIG_USERNAME, tmp, strlenn(tmp));
                    280:     nutss_config_set(NUTSS_CONFIG_PROXYUSERNAME, tmp, strlenn(tmp));
                    281:     nutss_config_set(NUTSS_CONFIG_PROXYPASSWORD, tmp, strlenn(tmp));
                    282:     strncpy(tmp, "nutss.net", sizeof(tmp));
                    283:     nutss_config_set(NUTSS_CONFIG_DOMAINNAME, tmp, strlenn(tmp));
                    284:     strncpy(tmp, "sip.nutss.net:5060", sizeof(tmp));
                    285:     nutss_config_set(NUTSS_CONFIG_SIGPROXY, tmp, strlenn(tmp));
                    286:
1.27      ths       287:     // open output files
1.24      ths       288:     if(num != 99) {
                    289:         sprintf(tmp, "output/data_node%d.txt", num); f = fopen(tmp,"w");
1.28      ths       290:         sprintf(tmp, "output/peer_node%d.txt", num); q = fopen(tmp,"w");
1.29      ths       291:         sprintf(tmp, "output/walk_node%d.txt", num); r = fopen(tmp,"w");
1.27      ths       292: //        sprintf(tmp, "output/output_node%d.txt", num); s = fopen(tmp,"w");
                    293: //        sprintf(tmp, "output/nbrs_node%d.txt", num); g = fopen(tmp,"w");
1.24      ths       294:         if (f == NULL) f = stderr;
                    295:         if (s == NULL) s = stdout;
                    296:     }
1.28      ths       297:     if(f) fprintf(f,"%d\n",capacity);
1.24      ths       298:
1.27      ths       299:     // build registrar uri
1.24      ths       300:     memset(&reg, 0, sizeof(reg));
                    301:     reg.family = AF_NUTSS;
                    302:     strncpy(reg.user, "ths1", sizeof(reg.user));
                    303:     strncpy(reg.domain, "nutss.net", sizeof(reg.domain));
                    304:     strncpy(reg.service, "swaplinksd", sizeof(reg.service));
1.27      ths       305:     // start up swaplinks and let it get going
                    306:     swaplinks_init(); swp = swaplinks_new("cloud9", &reg, peers, WALK_LENGTH); sleep(5);
1.24      ths       307:
                    308:     // coordinator thread
                    309:     if(num == 99) {
1.27      ths       310:         for(;time > 0;time--) {
                    311:             printf(" ---> %d MINUTE%s REMAIN%s\n",time,time==1?"":"S",time==1?"S":"");
1.28      ths       312:             clear(nbrs);
                    313:             swaplinks_get_neighbors(swp,nbrs,4096);
1.29      ths       314:             print_neighbor_list(nbrs);
1.28      ths       315:             p = process_neighbor_list(nbrs);
1.29      ths       316:             printf("Coordinator Nbrs: %d %d\n",p.i,p.o);
1.27      ths       317:             sleep(60);
1.24      ths       318:         }
1.27      ths       319:         printf("Now sending KILL signals\n",limit);
1.29      ths       320: //
                    321:         swaplinks_update_walk_length(swp,1);
                    322:         swaplinks_sendtoany(swp, "SHUTDOWN", 9, 0);
                    323:         swaplinks_update_walk_length(swp,WALK_LENGTH);
                    324: //
1.27      ths       325:         for(i = 0; i < nodes*REDUNDANCY; i++) swaplinks_sendtoany(swp, "SHUTDOWN", 9, 0);
1.25      ths       326:         // give them time to scramble
1.27      ths       327:         printf("Waiting for KILL signals to propagate\n");
                    328:         sleep(PROPAGATION);
1.26      ths       329:         // clean up their mess
1.27      ths       330:         printf("Forcibly removing remaining nodes and associated file\n");
1.26      ths       331:         system("find output -size 0c | xargs rm -rf");
1.29      ths       332:         // then kill stragglers more violently (including the coordinator)
1.32    ! ths       333:         system("killall lt-nutssd");
1.25      ths       334:         system("killall lt-slinksvariableload");
1.24      ths       335:         return 0;
                    336:     }
                    337:
1.29      ths       338:     exts = MIN_GRACE;
1.24      ths       339:     pthread_create(&tid, NULL, recvthread, swp);
1.27      ths       340:     // give recieving threads a chance to wake up
                    341:     sleep(5);
1.24      ths       342:
1.28      ths       343:     while (time++ < limit && alive) {
1.27      ths       344:         // send a request for resources with probability percent/100
1.29      ths       345:         if(randint(100) < percent) {
                    346:             snprintf(tmp,sizeof(tmp),"%d;%d;%d;%d%d;%d;%d;%d;",duration,weight,exts,num,time,capacity,capacity-load,peers);
1.27      ths       347:             swaplinks_sendtoany(swp,tmp,strlenn(tmp)+1, 0);
                    348:         }
                    349:         // record number and type of neighbors
                    350:       //  swaplinks_get_neighbors(swp,nbrs,4096);
                    351:       //  p = process_neighbor_list(nbrs);
                    352:       //  if(g) fprintf(g,"%d %d\n",p.i,p.o);
                    353:       //  clear(nbrs);
                    354:        // it might make more sense to sleep for more time between requests
1.29      ths       355:         sleep(12);
1.24      ths       356:     }
                    357:
1.27      ths       358:   //  if(g) fclose(g);
1.26      ths       359:     if(s) printf("%d DONE SENDING\n",num);
1.24      ths       360:     pthread_join(tid, NULL);
                    361:     if(s) fprintf(s,"%d SHUTTING DOWN\n",num);
                    362:
                    363:     return 0;
                    364: }
                    365:
1.28      ths       366: // read the neighbor list and extract the number of in and out nbrs
                    367: // would also like to alter this to give the number of unique nbrs
                    368: // instead of the raw number
1.24      ths       369: int_pair process_neighbor_list(char *s) {
1.29      ths       370:     int_pair p = {0,0};
                    371:     int inuniq[MAX_PEERS],outuniq[MAX_PEERS],inuniqs=0,outuniqs=0,newpeer,i;
                    372:     char temp[5],copy[URI_LENGTH];
                    373:     char *t,inseenit=0,outseenit;
1.24      ths       374:
1.29      ths       375:     memset(inuniq,0,MAX_PEERS*sizeof(int));
                    376:     memset(outuniq,0,MAX_PEERS*sizeof(int));
                    377:
                    378:     // avoid null strings altogether
1.24      ths       379:     if(!s) return p;
1.29      ths       380:     // move through the string one character at a time
1.24      ths       381:     while(*s) {
1.29      ths       382:         // if we have some characters left
                    383:         if(strlen(s) > 4) {
                    384:             // check if the next four chars are "test"
                    385:             strncpy(copy,s,URI_LENGTH);
                    386:             strncpy(temp,copy,4);
                    387:             if(streq(temp,"test")) {
                    388:                 // get number of peer and save it
                    389:                 newpeer = atoi(strtok(copy+4,"@"));
                    390:                 inseenit = outseenit = 0;
                    391:                 // check if we've seen this peer before
                    392:                 for(i=0;i<inuniqs;i++) {
                    393:                     if(inuniq[i] == newpeer) {
                    394:                         inseenit = 1;
                    395:                         break;
                    396:                     }
                    397:                 }
                    398:                 for(i=0;i<outuniqs;i++) {
                    399:                     if(outuniq[i] == newpeer) {
                    400:                         outseenit = 1;
                    401:                         break;
                    402:                     }
                    403:                 }
                    404:             }
                    405:         }
1.24      ths       406:         if(*s++ == '_') {
                    407:             switch(*s++) {
1.29      ths       408:                 // only record this nbr if we haven't seen it
                    409:                 case 'i': if(!inseenit) { p.i++; inuniq[inuniqs++] = newpeer; } break;
                    410:                 case 'o': if(!outseenit) { p.o++; outuniq[outuniqs++] = newpeer; } break;
1.24      ths       411:                 default: exit(s[-1]);
                    412:             }
                    413:         }
                    414:     }
                    415:     return p;
                    416: }
1.29      ths       417:
                    418: void print_neighbor_list(char *s) {
                    419:     int newpeer;
                    420:     char copy[URI_LENGTH],temp[5];
                    421:     char inp[256], outp[256];
                    422:     clear(inp); clear(outp);
                    423:     // avoid null strings altogether
                    424:     if(!s) return;
                    425:     // move through the string one character at a time
                    426:     while(*s) {
                    427:         // if we have some characters left
                    428:         if(strlen(s) > 4) {
                    429:             // check if the next four chars are "test"
                    430:             strncpy(copy,s,URI_LENGTH);
                    431:             strncpy(temp,copy,4);
                    432:             if(streq(temp,"test"))
                    433:                 newpeer = atoi(strtok(copy+4,"@"));
                    434:         }
                    435:         if(*s++ == '_') {
                    436:             switch(*s++) {
                    437:                 // only record this nbr if we haven't seen it
                    438:                 case 'i': sprintf(inp,"%s%d ",inp,newpeer); break;
                    439:                 case 'o': sprintf(outp,"%s%d ",outp,newpeer); break;
                    440:                 default: exit(s[-1]);
                    441:             }
                    442:         }
                    443:     }
                    444:     printf("in: %s\nout: %s\n",inp,outp);
                    445: }
                    446:
                    447:

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>
 

GForge.cis.cornell.edu is brought to you by

Cornell Computing and Information Science


Powered By GForge Collaborative Development Environment