nfs-ganesha 1.4
|
00001 #ifdef HAVE_CONFIG_H 00002 #include "config.h" 00003 #endif 00004 00005 #include <unistd.h> 00006 #include <stdlib.h> 00007 #include <stdio.h> 00008 00009 #include <string.h> 00010 00011 #include <limits.h> 00012 #include <ctype.h> 00013 00014 #include "nodelist.h" 00015 00016 #define DEFAULT_RANGELIST_SIZE 16 00017 #define DEFAULT_RANGELIST_INC_SIZE 8 00018 00019 int nodelist_range_set(nodelist_range_t * r1, long int v1, long int v2) 00020 { 00021 /* assert that lower and upper bound are in right order */ 00022 if(v1 <= v2) 00023 { 00024 r1->from = v1; 00025 r1->to = v2; 00026 } 00027 else 00028 { 00029 r1->from = v2; 00030 r1->to = v1; 00031 } 00032 return 0; 00033 } 00034 00035 int nodelist_range_check(nodelist_range_t * r1) 00036 { 00037 if((r1->from) <= (r1->to)) 00038 return 1; 00039 else 00040 return 0; 00041 } 00042 00043 int _nodelist_range_compare(const void *a1, const void *a2) 00044 { 00045 nodelist_range_t *r1 = (nodelist_range_t *) a1; 00046 nodelist_range_t *r2 = (nodelist_range_t *) a2; 00047 return nodelist_range_compare(r1, r2); 00048 } 00049 00050 int nodelist_range_compare(nodelist_range_t * r1, nodelist_range_t * r2) 00051 { 00052 int fstatus = 0; 00053 if(!nodelist_range_check(r1) || !nodelist_range_check(r2)) 00054 return fstatus; 00055 if(r1->from == r2->from && r1->to == r2->to) 00056 return 0; 00057 else if(r1->to < r2->from) 00058 return -1; 00059 else 00060 return 1; 00061 return fstatus; 00062 } 00063 00064 int nodelist_range_intersects(nodelist_range_t * r1, nodelist_range_t * r2) 00065 { 00066 int fstatus = 0; 00067 if(!nodelist_range_check(r1) || !nodelist_range_check(r2)) 00068 return fstatus; 00069 if(r2->to == r2->from) 00070 if(r1->from <= r2->to && r2->to <= r1->to) 00071 fstatus = 1; 00072 if(r1->to == r1->from) 00073 if(r2->from <= r1->to && r1->to <= r2->to) 00074 fstatus = 1; 00075 if(r2->to >= r1->from && r2->from <= r1->to) 00076 fstatus = 1; 00077 if(r1->to >= r2->from && r1->from <= r2->to) 00078 fstatus = 1; 00079 return fstatus; 00080 } 00081 00082 int 00083 nodelist_range_intersection(nodelist_range_t * r1, nodelist_range_t * r2, 00084 nodelist_range_t * rout) 00085 { 00086 int fstatus = -1; 00087 if(!nodelist_range_check(r1) || !nodelist_range_check(r2)) 00088 return fstatus; 00089 if(nodelist_range_intersects(r1, r2)) 00090 { 00091 rout->from = (r1->from > r2->from) ? r1->from : r2->from; 00092 rout->to = (r1->to < r2->to) ? r1->to : r2->to; 00093 fstatus = 0; 00094 } 00095 return fstatus; 00096 } 00097 00098 int nodelist_range_contiguous(nodelist_range_t * r1, nodelist_range_t * r2) 00099 { 00100 int fstatus = -1; 00101 if(!nodelist_range_check(r1) || !nodelist_range_check(r2)) 00102 return fstatus; 00103 if((r1->to + 1) != r2->from && (r1->from - 1) != r2->to) 00104 fstatus = 0; 00105 else if(r1->to < r2->from) 00106 fstatus = 1; 00107 else 00108 fstatus = 2; 00109 return fstatus; 00110 } 00111 00112 int nodelist_range_includes(nodelist_range_t * r1, nodelist_range_t * r2) 00113 { 00114 int fstatus = -1; 00115 if(!nodelist_range_check(r1) || !nodelist_range_check(r2)) 00116 { 00117 return fstatus; 00118 } 00119 if(r2->from >= r1->from && r2->to <= r1->to) 00120 fstatus = 1; 00121 else if(r1->from >= r2->from && r1->to <= r2->to) 00122 fstatus = 2; 00123 else 00124 fstatus = 0; 00125 return fstatus; 00126 } 00127 00128 int 00129 nodelist_range_union(nodelist_range_t * r1, nodelist_range_t * r2, 00130 nodelist_range_t * rout) 00131 { 00132 int fstatus = -1; 00133 if(!nodelist_range_check(r1) || !nodelist_range_check(r2)) 00134 return fstatus; 00135 if(!nodelist_range_intersects(r1, r2)) 00136 { 00137 if(!nodelist_range_contiguous(r1, r2)) 00138 return fstatus; 00139 } 00140 rout->from = (r1->from < r2->from) ? r1->from : r2->from; 00141 rout->to = (r1->to > r2->to) ? r1->to : r2->to; 00142 fstatus = 0; 00143 return fstatus; 00144 } 00145 00146 int nodelist_rangelist_init(nodelist_rangelist_t * array) 00147 { 00148 int fstatus = -1; 00149 array->pre_allocated_ranges = DEFAULT_RANGELIST_SIZE; 00150 array->ranges_nb = 0; 00151 array->array = 00152 (nodelist_range_t *) malloc(array->pre_allocated_ranges * sizeof(nodelist_range_t)); 00153 if(array->array != NULL) 00154 { 00155 fstatus = 0; 00156 } 00157 else 00158 { 00159 array->pre_allocated_ranges = 0; 00160 } 00161 return fstatus; 00162 } 00163 00164 int 00165 nodelist_rangelist_init_by_copy(nodelist_rangelist_t * array, nodelist_rangelist_t * a2c) 00166 { 00167 int fstatus = -11; 00168 int i; 00169 array->pre_allocated_ranges = a2c->pre_allocated_ranges; 00170 array->ranges_nb = a2c->ranges_nb; 00171 array->array = 00172 (nodelist_range_t *) malloc(array->pre_allocated_ranges * sizeof(nodelist_range_t)); 00173 if(array->array != NULL) 00174 { 00175 for(i = 0; i < array->ranges_nb; i++) 00176 { 00177 memcpy(((array->array) + i), ((a2c->array) + i), sizeof(nodelist_range_t)); 00178 } 00179 fstatus = 0; 00180 } 00181 else 00182 { 00183 array->pre_allocated_ranges = 0; 00184 } 00185 return fstatus; 00186 } 00187 00188 int nodelist_rangelist_free_contents(nodelist_rangelist_t * array) 00189 { 00190 int fstatus = 0; 00191 array->pre_allocated_ranges = 0; 00192 array->ranges_nb = 0; 00193 if(array->array != NULL) 00194 { 00195 free(array->array); 00196 array->array = NULL; 00197 } 00198 return fstatus; 00199 } 00200 00201 int nodelist_rangelist_incremente_size(nodelist_rangelist_t * array) 00202 { 00203 00204 int fstatus = -1; 00205 array->pre_allocated_ranges += DEFAULT_RANGELIST_INC_SIZE; 00206 array->array = 00207 (nodelist_range_t *) realloc(array->array, 00208 array->pre_allocated_ranges * 00209 sizeof(nodelist_range_t)); 00210 if(array->array != NULL) 00211 fstatus = 0; 00212 return fstatus; 00213 } 00214 00215 int nodelist_rangelist_add_range(nodelist_rangelist_t * array, nodelist_range_t * rin) 00216 { 00217 int fstatus = -1; 00218 int already_added_flag = 0; 00219 long int id; 00220 00221 nodelist_range_t r; 00222 nodelist_rangelist_t work_array; 00223 00224 memcpy(&r, rin, sizeof(nodelist_range_t)); 00225 if(array->ranges_nb == 0) 00226 { 00227 memcpy(array->array, &r, sizeof(nodelist_range_t)); 00228 array->ranges_nb++; 00229 fstatus = 0; 00230 } 00231 else 00232 { 00233 /* test if range is already present */ 00234 for(id = 0; id < array->ranges_nb; id++) 00235 { 00236 already_added_flag = nodelist_range_includes(&(array->array[id]), &r); 00237 if(already_added_flag == 1) 00238 break; 00239 already_added_flag = 0; 00240 } 00241 /* add range if not already present */ 00242 if(already_added_flag) 00243 { 00244 fstatus = 0; 00245 } 00246 else 00247 { 00248 /* initialize working ranges array */ 00249 nodelist_rangelist_init(&work_array); 00250 /* process sequentially input ranges array 's ranges */ 00251 for(id = 0; id < array->ranges_nb; id++) 00252 { 00253 /* if range to add doesn't intersect or is not contiguous to currently tested range */ 00254 /* of the input ranges array, we add it to working ranges array */ 00255 /* otherwise, we merge it with current tested range of the input ranges array and go */ 00256 /* to the next range */ 00257 if(!nodelist_range_intersects(&(array->array[id]), &r) 00258 && !nodelist_range_contiguous(&(array->array[id]), &r)) 00259 { 00260 if(work_array.ranges_nb == work_array.pre_allocated_ranges) 00261 nodelist_rangelist_incremente_size(&work_array); 00262 memcpy(work_array.array + work_array.ranges_nb, &(array->array[id]), 00263 sizeof(nodelist_range_t)); 00264 work_array.ranges_nb++; 00265 } 00266 else 00267 { 00268 nodelist_range_union(&(array->array[id]), &r, &r); 00269 } 00270 } 00271 /* add range to add (which may be bigger now ) */ 00272 if(work_array.ranges_nb == work_array.pre_allocated_ranges) 00273 nodelist_rangelist_incremente_size(&work_array); 00274 memcpy(work_array.array + work_array.ranges_nb, &r, sizeof(nodelist_range_t)); 00275 work_array.ranges_nb++; 00276 nodelist_rangelist_sort(&work_array); 00277 00278 nodelist_rangelist_free_contents(array); 00279 fstatus = nodelist_rangelist_init_by_copy(array, &work_array); 00280 } 00281 } 00282 00283 return fstatus; 00284 } 00285 00286 int 00287 nodelist_rangelist_add_rangelist(nodelist_rangelist_t * array, 00288 nodelist_rangelist_t * rlin) 00289 { 00290 int fstatus = 0; 00291 00292 int i; 00293 00294 for(i = 0; i < rlin->ranges_nb; i++) 00295 { 00296 fstatus += nodelist_rangelist_add_range(array, &(rlin->array[i])); 00297 } 00298 00299 return fstatus; 00300 } 00301 00302 int nodelist_rangelist_remove_range(nodelist_rangelist_t * array, nodelist_range_t * rin) 00303 { 00304 int fstatus = -1; 00305 int intersects_flag = 0; 00306 long int id; 00307 00308 nodelist_range_t *pr; 00309 nodelist_range_t r; 00310 nodelist_range_t wr1; 00311 nodelist_rangelist_t work_array; 00312 00313 if(array->ranges_nb == 0) 00314 { 00315 fstatus = 0; 00316 } 00317 else 00318 { 00319 memcpy(&r, rin, sizeof(nodelist_range_t)); 00320 /* initialize working ranges array */ 00321 nodelist_rangelist_init(&work_array); 00322 /* test if range intersects with this rangelist */ 00323 intersects_flag = 0; 00324 fstatus = 0; 00325 for(id = 0; id < array->ranges_nb; id++) 00326 { 00327 pr = &(array->array[id]); 00328 intersects_flag = nodelist_range_intersects(pr, &r); 00329 if(!intersects_flag) 00330 { 00331 /* add this range to work array */ 00332 fstatus += nodelist_rangelist_add_range(&work_array, pr); 00333 } 00334 else 00335 { 00336 /* extract any hypothetic non intersecting part of the range */ 00337 /* and add them to work_array range list */ 00338 if(pr->from != pr->to) 00339 { 00340 /* check that second range doesn't include the first one */ 00341 if(nodelist_range_includes(&r, pr) != 1) 00342 { 00343 /* [pr[r... */ 00344 if(pr->from < r.from) 00345 { 00346 nodelist_range_set(&wr1, pr->from, r.from - 1); 00347 fstatus += nodelist_rangelist_add_range(&work_array, &wr1); 00348 } 00349 /* ...r]pr] */ 00350 if(pr->to > r.to) 00351 { 00352 nodelist_range_set(&wr1, r.to + 1, pr->to); 00353 fstatus += nodelist_rangelist_add_range(&work_array, &wr1); 00354 } 00355 00356 } 00357 /*_*/ 00358 } 00359 /*_*/ 00360 00361 } 00362 00363 if(fstatus) 00364 break; 00365 00366 } 00367 00368 /* success, replace array with the new range list */ 00369 if(fstatus == 0) 00370 { 00371 nodelist_rangelist_free_contents(array); 00372 fstatus = nodelist_rangelist_init_by_copy(array, &work_array); 00373 } 00374 00375 nodelist_rangelist_free_contents(&work_array); 00376 } 00377 00378 return fstatus; 00379 } 00380 00381 int 00382 nodelist_rangelist_remove_rangelist(nodelist_rangelist_t * array, 00383 nodelist_rangelist_t * rlin) 00384 { 00385 int fstatus = 0; 00386 00387 int i; 00388 00389 for(i = 0; i < rlin->ranges_nb; i++) 00390 { 00391 fstatus += nodelist_rangelist_remove_range(array, &(rlin->array[i])); 00392 } 00393 00394 return fstatus; 00395 } 00396 00397 int nodelist_rangelist_add_list(nodelist_rangelist_t * array, char *list) 00398 { 00399 int fstatus = 0; 00400 char *in_list; 00401 size_t in_list_size; 00402 char *work_buffer; 00403 char *begin; 00404 char *end; 00405 00406 long int start_val = 0; 00407 long int value; 00408 long int work_val; 00409 int start_flag = 0; 00410 int stop_flag = 0; 00411 00412 int padding = 0; 00413 00414 in_list = list; 00415 in_list_size = strlen(in_list); 00416 00417 /* create working buffer */ 00418 work_buffer = (char *)malloc(in_list_size + 1); 00419 if(work_buffer == NULL) 00420 { 00421 fstatus = -1; 00422 } 00423 else 00424 { 00425 /* set entry point */ 00426 begin = in_list; 00427 if(*begin == '[') 00428 begin++; 00429 end = begin; 00430 00431 /* process input list */ 00432 while(end != '\0' && end < in_list + in_list_size + 1) 00433 { 00434 while(isdigit(*end)) 00435 end++; 00436 /* do something only if end was incremented */ 00437 if(end - begin) 00438 { 00439 /* extract the read value */ 00440 strncpy(work_buffer, begin, (end - begin)); 00441 work_buffer[end - begin] = '\0'; 00442 /* get long int value and test its validity */ 00443 value = strtoll(work_buffer, NULL, 10); 00444 if(value == LONG_MIN || value == LONG_MAX) 00445 { 00446 fstatus = 2; 00447 break; 00448 } 00449 /* try to get padding */ 00450 if(*work_buffer == '0') 00451 { 00452 int max_length = strlen(work_buffer); 00453 if(max_length > padding) 00454 { 00455 padding = max_length; 00456 } 00457 } 00458 00459 /* check how many value must be added */ 00460 if(*end == '\0' || *end == ',' || *end == ']') 00461 { 00462 if(!start_flag) 00463 { 00464 start_flag = 1; 00465 start_val = value; 00466 } 00467 stop_flag = 1; 00468 } 00469 /* current lemme is a range */ 00470 else if(*end == '-') 00471 { 00472 start_flag = 1; 00473 start_val = value; 00474 } 00475 /* current lemme has a invalid format */ 00476 else 00477 { 00478 fstatus = 3; 00479 break; 00480 } 00481 00482 /* test if value(s) must be added now */ 00483 if(start_flag && stop_flag) 00484 { 00485 if(value < start_val) 00486 { 00487 work_val = start_val; 00488 start_val = value; 00489 value = work_val; 00490 } 00491 /* add value(s) */ 00492 nodelist_range_t br; 00493 nodelist_range_set(&br, start_val, value); 00494 nodelist_rangelist_add_range(array, &br); 00495 start_flag = 0; 00496 stop_flag = 0; 00497 } 00498 } 00499 /* go to next lemme */ 00500 end++; 00501 begin = end; 00502 } 00503 00504 /* free working buffer */ 00505 free(work_buffer); 00506 00507 } 00508 00509 /* at this point fstatus=0 if process was done succesfully, we may update it to padding value */ 00510 if(fstatus != 0) 00511 fstatus = -1; 00512 else 00513 fstatus = padding; 00514 00515 return fstatus; 00516 } 00517 00518 int nodelist_rangelist_sort(nodelist_rangelist_t * array) 00519 { 00520 int fstatus = -1; 00521 qsort(array->array, array->ranges_nb, sizeof(nodelist_range_t), 00522 _nodelist_range_compare); 00523 return fstatus; 00524 } 00525 00526 int nodelist_rangelist_intersects(nodelist_rangelist_t * a1, nodelist_rangelist_t * a2) 00527 { 00528 int fstatus = 0; 00529 int i, j; 00530 for(i = 0; i < a1->ranges_nb; i++) 00531 { 00532 for(j = 0; j < a2->ranges_nb; j++) 00533 { 00534 fstatus = nodelist_range_intersects(&(a1->array[i]), &(a2->array[j])); 00535 if(fstatus) 00536 break; 00537 } 00538 if(fstatus) 00539 break; 00540 } 00541 return fstatus; 00542 } 00543 00544 int nodelist_rangelist_includes(nodelist_rangelist_t * a1, nodelist_rangelist_t * a2) 00545 { 00546 int fstatus = 0; 00547 int i, j; 00548 int valid_ranges_nb = 0; 00549 for(i = 0; i < a2->ranges_nb; i++) 00550 { 00551 for(j = 0; j < a1->ranges_nb; j++) 00552 { 00553 if(nodelist_range_includes(&(a1->array[j]), &(a2->array[i])) == 1) 00554 { 00555 valid_ranges_nb++; 00556 break; 00557 } 00558 } 00559 } 00560 if(valid_ranges_nb == a2->ranges_nb) 00561 fstatus = 1; 00562 return fstatus; 00563 } 00564 00565 int nodelist_rangelist_show(nodelist_rangelist_t * array) 00566 { 00567 long int id; 00568 fprintf(stdout, "----------------------------------\n"); 00569 fprintf(stdout, "Ranges nb : %lu\n", array->ranges_nb); 00570 for(id = 0; id < array->ranges_nb; id++) 00571 { 00572 fprintf(stdout, "[%lu-%lu]\n", array->array[id].from, array->array[id].to); 00573 } 00574 fprintf(stdout, "----------------------------------\n"); 00575 return 0; 00576 }