XrdFfsDent.cc

Go to the documentation of this file.
00001 /******************************************************************************/
00002 /* XrdFfsDent.cc  help functions to merge direntries                          */
00003 /*                                                                            */
00004 /* (c) 2010 by the Board of Trustees of the Leland Stanford, Jr., University  */
00005 /*                            All Rights Reserved                             */
00006 /* Author: Wei Yang (SLAC National Accelerator Laboratory, 2009)              */
00007 /*         Contract DE-AC02-76-SFO0515 with the Department of Energy          */
00008 /******************************************************************************/
00009 
00010 #include "XrdFfs/XrdFfsDent.hh"
00011 
00012 #ifdef __cplusplus
00013   extern "C" {
00014 #endif
00015 
00016 /*
00017   to be used by quick sort
00018  */
00019 int XrdFfsDent_cstr_cmp(const void *a, const void *b)
00020 {
00021     const char **aa = (const char **)a;
00022     const char **bb = (const char **)b;
00023     return strcmp(*aa, *bb);
00024 }
00025 
00026 /*
00027   _del() frees the head node of *p
00028  */
00029 void XrdFfsDent_names_del(struct XrdFfsDentnames **p)
00030 {
00031     (*p)->name = NULL;
00032     (*p)->next = NULL;
00033     free(*p);
00034 } 
00035 
00036 void XrdFfsDent_names_add(struct XrdFfsDentnames **p, char *name)
00037 {
00038     struct XrdFfsDentnames *n = (struct XrdFfsDentnames*)malloc(sizeof(struct XrdFfsDentnames));
00039     n->name = strdup(name);
00040 
00041     n->next = *p;
00042     *p = n;
00043     return; 
00044 }
00045 
00046 /*
00047   _join() joins *n to *p. Note *p or *n may equal to NULL. In that
00048   case, old *p is remove and *p will equal to *n in the end.
00049 
00050   Giving list A, B, C and one want to join in the order of A->B->C 
00051   (so that A points to the joined final list), there are two ways 
00052   to to this:
00053 
00054   1. _join(&A, &B); _join(&A, &C) (not efficient)
00055   2. _join(&B, &C); _join(&A, &B) (efficient)
00056 
00057  */
00058 void XrdFfsDent_names_join(struct XrdFfsDentnames **p, struct XrdFfsDentnames **n)
00059 {
00060     struct XrdFfsDentnames *t, *l;
00061 
00062     if ( *p != NULL )
00063     {
00064         t = *p;
00065         while ( t != NULL ) 
00066         {
00067             l = t;
00068             t = t->next;
00069         }
00070         l->next = *n;
00071     }
00072     else
00073         *p = *n;
00074 }
00075 
00076 /* 
00077    _extract() returns (to dnarray) a char array with all (*p)->name 
00078    sorted accroding to strcmp(), and destroy *p.
00079 */
00080 int XrdFfsDent_names_extract(struct XrdFfsDentnames **p, char ***dnarray)
00081 {
00082     struct XrdFfsDentnames *x, *y;
00083     int i = 0;
00084 
00085     y = *p; 
00086     while (y != NULL) 
00087     {
00088         i++;
00089         y = y->next;
00090     }
00091     /* be careful, old dnarray is lost */
00092     *dnarray = (char**) malloc(sizeof(char*) * i);
00093 
00094     x = *p;
00095     y = *p; 
00096     i = 0;
00097     while (y != NULL) 
00098     {
00099         (*dnarray)[i++] = y->name;
00100         y = y->next;
00101         XrdFfsDent_names_del(&x);
00102         x = y;
00103     }
00104 
00105     qsort((*dnarray), i, sizeof(char*), XrdFfsDent_cstr_cmp);
00106     *p = NULL;
00107     return i;
00108 }
00109 
00110 /* managing caches for dentnames */
00111 
00112 struct XrdFfsDentcache {
00113     time_t t0;
00114     time_t life;
00115     unsigned int nents;
00116     char *dirname;
00117     char **dnarray;
00118 };
00119 
00120 void XrdFfsDent_dentcache_fill(struct XrdFfsDentcache *cache, char *dname, char ***dnarray, int nents)
00121 {
00122     int i;
00123 
00124     cache->dirname = strdup(dname);
00125     cache->nents = nents;
00126     cache->t0 = time(NULL);
00127     cache->life = nents / 20 ;
00128     cache->dnarray = (char**) malloc(sizeof(char*) * nents);
00129     
00130     for (i = 0; i < nents; i++)
00131         cache->dnarray[i] = strdup((*dnarray)[i]);
00132 }
00133 
00134 void XrdFfsDent_dentcache_free(struct XrdFfsDentcache *cache)
00135 {
00136     int i;
00137     for (i = 0; i < (int)cache->nents; i++)
00138     {
00139         free(cache->dnarray[i]);
00140     }    
00141     cache->nents = 0;
00142     free(cache->dnarray);
00143     free(cache->dirname);
00144     cache->dnarray = NULL;
00145     cache->dirname = NULL;
00146 }
00147 
00148 /* expired cache may still be useful. invalid cache should not be used */
00149 int  XrdFfsDent_dentcache_expired(struct XrdFfsDentcache *cache)
00150 {
00151     time_t t1;
00152     t1 = time(NULL);
00153     return (((t1 - cache->t0) < cache->life)? 0 : 1);
00154 }
00155 
00156 int  XrdFfsDent_dentcache_invalid(struct XrdFfsDentcache *cache)
00157 {
00158     time_t t1;
00159     t1 = time(NULL);
00160     return (((t1 - cache->t0) < 28700)? 0 : 1); // after 8 hours (28800 sec), the redirector no longer remembers
00161 }
00162 
00163 int  XrdFfsDent_dentcache_search(struct XrdFfsDentcache *cache, char *dname, char *dentname)
00164 {
00165     char path[1024]; 
00166 
00167     strcpy(path, dname);
00168     if (dentname != NULL && path[strlen(path) -1] != '/') 
00169         strcat(path,"/");
00170     if (dentname != NULL) strcat(path, dentname);
00171     if (XrdFfsDent_dentcache_invalid(cache))
00172         return 0;
00173     else if (strlen(cache->dirname) == strlen(path) && strcmp(cache->dirname, path) == 0) 
00174         return 1;
00175     else if (strlen(cache->dirname) != strlen(dname) || strcmp(cache->dirname, dname) != 0) 
00176         return 0;
00177     else if (bsearch(&dentname, cache->dnarray, cache->nents, sizeof(char*), XrdFfsDent_cstr_cmp) != NULL)
00178         return 1;
00179     else
00180         return 0;
00181 }
00182 
00183 #define XrdFfsDent_NDENTCACHES 20 
00184 struct XrdFfsDentcache XrdFfsDentCaches[XrdFfsDent_NDENTCACHES];
00185 pthread_mutex_t XrdFfsDentCaches_mutex = PTHREAD_MUTEX_INITIALIZER;
00186 
00187 void XrdFfsDent_cache_init()
00188 {
00189     int i;
00190     for (i = 0; i < XrdFfsDent_NDENTCACHES; i++)
00191     {
00192         XrdFfsDentCaches[i].t0 = 0;
00193         XrdFfsDentCaches[i].nents = 0;
00194         XrdFfsDentCaches[i].dirname = strdup("");
00195         XrdFfsDentCaches[i].dnarray = NULL;
00196     }
00197 }
00198 
00199 int XrdFfsDent_cache_fill(char *dname, char ***dnarray, int nents)
00200 {
00201     int i;
00202     pthread_mutex_lock(&XrdFfsDentCaches_mutex);
00203     for (i = 0; i < XrdFfsDent_NDENTCACHES; i++)
00204     {
00205         if (XrdFfsDent_dentcache_search(&XrdFfsDentCaches[i], dname, NULL) != 0)
00206         {
00207             XrdFfsDent_dentcache_free(&XrdFfsDentCaches[i]);
00208             XrdFfsDent_dentcache_fill(&XrdFfsDentCaches[i], dname, dnarray, nents); 
00209             pthread_mutex_unlock(&XrdFfsDentCaches_mutex);
00210             return 1;
00211         } 
00212     }
00213     for (i = 0; i < XrdFfsDent_NDENTCACHES; i++)
00214     {
00215         if (XrdFfsDent_dentcache_expired(&XrdFfsDentCaches[i]) || XrdFfsDent_dentcache_invalid(&XrdFfsDentCaches[i])) 
00216         {
00217             XrdFfsDent_dentcache_free(&XrdFfsDentCaches[i]);
00218             XrdFfsDent_dentcache_fill(&XrdFfsDentCaches[i], dname, dnarray, nents); 
00219             pthread_mutex_unlock(&XrdFfsDentCaches_mutex);
00220             return 1;
00221         }
00222     }
00223     pthread_mutex_unlock(&XrdFfsDentCaches_mutex);
00224     return 0;
00225 }
00226 
00227 int XrdFfsDent_cache_search(char *dname, char *dentname)
00228 {
00229     int i, rval = 0;
00230     pthread_mutex_lock(&XrdFfsDentCaches_mutex);
00231     for (i = 0; i < XrdFfsDent_NDENTCACHES; i++)
00232         if (XrdFfsDent_dentcache_search(&XrdFfsDentCaches[i], dname, dentname) == 1) 
00233         {
00234             rval = 1;
00235             break;
00236         }
00237     pthread_mutex_unlock(&XrdFfsDentCaches_mutex);
00238     return rval;
00239 }
00240 
00241 void XrdFfsDent_cache_destroy()
00242 {
00243     int i;
00244     for (i = 0; i < XrdFfsDent_NDENTCACHES; i++)
00245         XrdFfsDent_dentcache_free(&XrdFfsDentCaches[i]);
00246 }
00247 
00248 /*
00249 #include <stdio.h>
00250 
00251 main() 
00252 {
00253     struct XrdFfsDentnames *x = NULL;
00254     struct XrdFfsDentnames *y = NULL;
00255     struct XrdFfsDentnames *z = NULL;
00256     int totdentnames;
00257     int i = 0;
00258     char **dnarray;
00259 
00260     XrdFfsDent_names_add(&x, "aaa");
00261     XrdFfsDent_names_add(&x, "bbb");
00262     XrdFfsDent_names_add(&x, "ccc");
00263 
00264     XrdFfsDent_names_add(&y, "aaa");
00265     XrdFfsDent_names_add(&y, "aa");
00266     XrdFfsDent_names_add(&y, "bb");
00267 
00268     XrdFfsDent_names_add(&z, "xxx");
00269 
00270     XrdFfsDent_names_join(&z, &y);
00271     XrdFfsDent_names_join(&x, &z);
00272 
00273     totdentnames = XrdFfsDent_names_extract(&x, &dnarray);
00274     char *last, *name;
00275     for (i=0; i<totdentnames; i++)
00276     {
00277         if (i==0 || strcmp(last, dnarray[i]) != 0)
00278         { 
00279             name = strdup(dnarray[i]);
00280             printf(" :== %s\n", name);
00281             free(name);
00282             last = dnarray[i];
00283         }
00284     }
00285 
00286     XrdFfsDent_cache_init();
00287     XrdFfsDent_cache_fill("/opt", &dnarray, totdentnames);
00288     printf("searching /opt/aa : %d\n", XrdFfsDent_cache_search("/opt", "aa"));
00289     printf("searching /opm/aa : %d\n", XrdFfsDent_cache_search("/opm", "aa"));
00290     printf("searching /opt/dd : %d\n", XrdFfsDent_cache_search("/opt", "dd"));
00291     sleep(3);
00292     printf("searching /opt/aa : %d\n", XrdFfsDent_cache_search("/opt", "aa"));
00293     sleep(3);
00294     printf("searching /opt/aa : %d\n", XrdFfsDent_cache_search("/opt", "aa"));
00295     XrdFfsDent_cache_destroy();
00296 
00297     XrdFfsDent_cache_init();
00298     i = XrdFfsDent_cache_fill("/opt0", &dnarray, totdentnames);
00299     sleep(7);
00300     i = XrdFfsDent_cache_fill("/opt1", &dnarray, totdentnames);
00301     i = XrdFfsDent_cache_fill("/opt2", &dnarray, totdentnames);
00302     i = XrdFfsDent_cache_fill("/opt3", &dnarray, totdentnames);
00303     i = XrdFfsDent_cache_fill("/opt4", &dnarray, totdentnames);
00304     i = XrdFfsDent_cache_fill("/opt5", &dnarray, totdentnames);
00305     
00306     printf("searching /opt0/aa : %d\n", XrdFfsDent_cache_search("/opt0","aa"));
00307     printf("searching /opt1/aa : %d\n", XrdFfsDent_cache_search("/opt1","aa"));
00308     printf("searching /opt2/aa : %d\n", XrdFfsDent_cache_search("/opt2","aa"));
00309     printf("searching /opt3/aa : %d\n", XrdFfsDent_cache_search("/opt3","aa"));
00310     printf("searching /opt4/aa : %d\n", XrdFfsDent_cache_search("/opt4","aa"));
00311     printf("searching /opt5/aa : %d\n", XrdFfsDent_cache_search("/opt5","aa"));
00312     XrdFfsDent_cache_destroy();
00313     for (i=0; i<totdentnames; i++)
00314     {
00315         free(dnarray[i]);
00316     }
00317     free(dnarray);
00318     exit(0);
00319 }
00320 */
00321 
00322 #ifdef __cplusplus
00323   }
00324 #endif

Generated on Tue Jul 5 14:46:34 2011 for ROOT_528-00b_version by  doxygen 1.5.1