nfs-ganesha 1.4

nodelist_range.c

Go to the documentation of this file.
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 }