XRootD
XrdFfsDent.cc
Go to the documentation of this file.
1 /******************************************************************************/
2 /* XrdFfsDent.cc help functions to merge direntries */
3 /* */
4 /* (c) 2010 by the Board of Trustees of the Leland Stanford, Jr., University */
5 /* All Rights Reserved */
6 /* Author: Wei Yang (SLAC National Accelerator Laboratory, 2009) */
7 /* Contract DE-AC02-76-SFO0515 with the Department of Energy */
8 /* */
9 /* This file is part of the XRootD software suite. */
10 /* */
11 /* XRootD is free software: you can redistribute it and/or modify it under */
12 /* the terms of the GNU Lesser General Public License as published by the */
13 /* Free Software Foundation, either version 3 of the License, or (at your */
14 /* option) any later version. */
15 /* */
16 /* XRootD is distributed in the hope that it will be useful, but WITHOUT */
17 /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
18 /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */
19 /* License for more details. */
20 /* */
21 /* You should have received a copy of the GNU Lesser General Public License */
22 /* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */
23 /* COPYING (GPL license). If not, see <http://www.gnu.org/licenses/>. */
24 /* */
25 /* The copyright holder's institutional names and contributor's names may not */
26 /* be used to endorse or promote products derived from this software without */
27 /* specific prior written permission of the institution or contributor. */
28 /******************************************************************************/
29 
30 #include "XrdFfs/XrdFfsDent.hh"
31 
32 #ifdef __cplusplus
33  extern "C" {
34 #endif
35 
36 /*
37  to be used by quick sort
38  */
39 int XrdFfsDent_cstr_cmp(const void *a, const void *b)
40 {
41  const char **aa = (const char **)a;
42  const char **bb = (const char **)b;
43  return strcmp(*aa, *bb);
44 }
45 
46 /*
47  _del() frees the head node of *p
48  */
50 {
51  (*p)->name = NULL;
52  (*p)->next = NULL;
53  free(*p);
54 }
55 
56 void XrdFfsDent_names_add(struct XrdFfsDentnames **p, char *name)
57 {
58  struct XrdFfsDentnames *n = (struct XrdFfsDentnames*)malloc(sizeof(struct XrdFfsDentnames));
59  n->name = strdup(name);
60 
61  n->next = *p;
62  *p = n;
63  return;
64 }
65 
66 /*
67  _join() joins *n to *p. Note *p or *n may equal to NULL. In that
68  case, old *p is remove and *p will equal to *n in the end.
69 
70  Giving list A, B, C and one want to join in the order of A->B->C
71  (so that A points to the joined final list), there are two ways
72  to to this:
73 
74  1. _join(&A, &B); _join(&A, &C) (not efficient)
75  2. _join(&B, &C); _join(&A, &B) (efficient)
76 
77  */
79 {
80  struct XrdFfsDentnames *t, *l = 0;
81 
82  if ( *p != NULL )
83  {
84  t = *p;
85  while ( t != NULL )
86  {
87  l = t;
88  t = t->next;
89  }
90  l->next = *n;
91  }
92  else
93  *p = *n;
94 }
95 
96 /*
97  _extract() returns (to dnarray) a char array with all (*p)->name
98  sorted accroding to strcmp(), and destroy *p.
99 */
100 int XrdFfsDent_names_extract(struct XrdFfsDentnames **p, char ***dnarray)
101 {
102  struct XrdFfsDentnames *x, *y;
103  int i = 0;
104 
105  y = *p;
106  while (y != NULL)
107  {
108  i++;
109  y = y->next;
110  }
111  /* be careful, old dnarray is lost */
112  *dnarray = (char**) malloc(sizeof(char*) * i);
113 
114  x = *p;
115  y = *p;
116  i = 0;
117  while (y != NULL)
118  {
119  (*dnarray)[i++] = y->name;
120  y = y->next;
122  x = y;
123  }
124 
125  qsort((*dnarray), i, sizeof(char*), XrdFfsDent_cstr_cmp);
126  *p = NULL;
127  return i;
128 }
129 
130 /* managing caches for dentnames */
131 
133  time_t t0;
134  time_t life;
135  unsigned int nents;
136  char *dirname;
137  char **dnarray;
138 };
139 
140 void XrdFfsDent_dentcache_fill(struct XrdFfsDentcache *cache, char *dname, char ***dnarray, int nents)
141 {
142  int i;
143 
144  cache->dirname = strdup(dname);
145  cache->nents = nents;
146  cache->t0 = time(NULL);
147  cache->life = nents / 10 ;
148  cache->dnarray = (char**) malloc(sizeof(char*) * nents);
149 
150  for (i = 0; i < nents; i++)
151  cache->dnarray[i] = strdup((*dnarray)[i]);
152 }
153 
155 {
156  int i;
157  for (i = 0; i < (int)cache->nents; i++)
158  {
159  free(cache->dnarray[i]);
160  }
161  cache->nents = 0;
162  free(cache->dnarray);
163  free(cache->dirname);
164  cache->dnarray = NULL;
165  cache->dirname = NULL;
166 }
167 
168 /* expired cache may still be useful. invalid cache should not be used */
170 {
171  time_t t1;
172  t1 = time(NULL);
173  return (((t1 - cache->t0) < cache->life)? 0 : 1);
174 }
175 
177 {
178  time_t t1;
179  t1 = time(NULL);
180  return (((t1 - cache->t0) < 28700)? 0 : 1); // after 8 hours (28800 sec), the redirector no longer remembers
181 }
182 
183 int XrdFfsDent_dentcache_search(struct XrdFfsDentcache *cache, char *dname, char *dentname)
184 {
185  char path[1024];
186 
187  strcpy(path, dname);
188  if (dentname != NULL && path[strlen(path) -1] != '/')
189  strcat(path,"/");
190  if (dentname != NULL) strcat(path, dentname);
191  if (XrdFfsDent_dentcache_invalid(cache))
192  return 0;
193  else if (strlen(cache->dirname) == strlen(path) && strcmp(cache->dirname, path) == 0)
194  return 1;
195  else if (strlen(cache->dirname) != strlen(dname) || strcmp(cache->dirname, dname) != 0)
196  return 0;
197  else if (bsearch(&dentname, cache->dnarray, cache->nents, sizeof(char*), XrdFfsDent_cstr_cmp) != NULL)
198  return 1;
199  else
200  return 0;
201 }
202 
203 #define XrdFfsDent_NDENTCACHES 20
205 pthread_mutex_t XrdFfsDentCaches_mutex = PTHREAD_MUTEX_INITIALIZER;
206 
208 {
209  int i;
210  for (i = 0; i < XrdFfsDent_NDENTCACHES; i++)
211  {
212  XrdFfsDentCaches[i].t0 = 0;
213  XrdFfsDentCaches[i].nents = 0;
214  XrdFfsDentCaches[i].dirname = strdup("");
215  XrdFfsDentCaches[i].dnarray = NULL;
216  }
217 }
218 
219 int XrdFfsDent_cache_fill(char *dname, char ***dnarray, int nents)
220 {
221  int i;
222  pthread_mutex_lock(&XrdFfsDentCaches_mutex);
223  for (i = 0; i < XrdFfsDent_NDENTCACHES; i++)
224  {
225  if (XrdFfsDent_dentcache_search(&XrdFfsDentCaches[i], dname, NULL) != 0)
226  {
229  pthread_mutex_unlock(&XrdFfsDentCaches_mutex);
230  return 1;
231  }
232  }
233  for (i = 0; i < XrdFfsDent_NDENTCACHES; i++)
234  {
236  {
239  pthread_mutex_unlock(&XrdFfsDentCaches_mutex);
240  return 1;
241  }
242  }
243  pthread_mutex_unlock(&XrdFfsDentCaches_mutex);
244  return 0;
245 }
246 
247 int XrdFfsDent_cache_search(char *dname, char *dentname)
248 {
249  int i, rval = 0;
250  pthread_mutex_lock(&XrdFfsDentCaches_mutex);
251  for (i = 0; i < XrdFfsDent_NDENTCACHES; i++)
252  if (XrdFfsDent_dentcache_search(&XrdFfsDentCaches[i], dname, dentname) == 1)
253  {
254  rval = 1;
255  break;
256  }
257  pthread_mutex_unlock(&XrdFfsDentCaches_mutex);
258  return rval;
259 }
260 
262 {
263  int i;
264  for (i = 0; i < XrdFfsDent_NDENTCACHES; i++)
266 }
267 
268 /*
269 #include <cstdio>
270 
271 main()
272 {
273  struct XrdFfsDentnames *x = NULL;
274  struct XrdFfsDentnames *y = NULL;
275  struct XrdFfsDentnames *z = NULL;
276  int totdentnames;
277  int i = 0;
278  char **dnarray;
279 
280  XrdFfsDent_names_add(&x, "aaa");
281  XrdFfsDent_names_add(&x, "bbb");
282  XrdFfsDent_names_add(&x, "ccc");
283 
284  XrdFfsDent_names_add(&y, "aaa");
285  XrdFfsDent_names_add(&y, "aa");
286  XrdFfsDent_names_add(&y, "bb");
287 
288  XrdFfsDent_names_add(&z, "xxx");
289 
290  XrdFfsDent_names_join(&z, &y);
291  XrdFfsDent_names_join(&x, &z);
292 
293  totdentnames = XrdFfsDent_names_extract(&x, &dnarray);
294  char *last, *name;
295  for (i=0; i<totdentnames; i++)
296  {
297  if (i==0 || strcmp(last, dnarray[i]) != 0)
298  {
299  name = strdup(dnarray[i]);
300  printf(" :== %s\n", name);
301  free(name);
302  last = dnarray[i];
303  }
304  }
305 
306  XrdFfsDent_cache_init();
307  XrdFfsDent_cache_fill("/opt", &dnarray, totdentnames);
308  printf("searching /opt/aa : %d\n", XrdFfsDent_cache_search("/opt", "aa"));
309  printf("searching /opm/aa : %d\n", XrdFfsDent_cache_search("/opm", "aa"));
310  printf("searching /opt/dd : %d\n", XrdFfsDent_cache_search("/opt", "dd"));
311  sleep(3);
312  printf("searching /opt/aa : %d\n", XrdFfsDent_cache_search("/opt", "aa"));
313  sleep(3);
314  printf("searching /opt/aa : %d\n", XrdFfsDent_cache_search("/opt", "aa"));
315  XrdFfsDent_cache_destroy();
316 
317  XrdFfsDent_cache_init();
318  i = XrdFfsDent_cache_fill("/opt0", &dnarray, totdentnames);
319  sleep(7);
320  i = XrdFfsDent_cache_fill("/opt1", &dnarray, totdentnames);
321  i = XrdFfsDent_cache_fill("/opt2", &dnarray, totdentnames);
322  i = XrdFfsDent_cache_fill("/opt3", &dnarray, totdentnames);
323  i = XrdFfsDent_cache_fill("/opt4", &dnarray, totdentnames);
324  i = XrdFfsDent_cache_fill("/opt5", &dnarray, totdentnames);
325 
326  printf("searching /opt0/aa : %d\n", XrdFfsDent_cache_search("/opt0","aa"));
327  printf("searching /opt1/aa : %d\n", XrdFfsDent_cache_search("/opt1","aa"));
328  printf("searching /opt2/aa : %d\n", XrdFfsDent_cache_search("/opt2","aa"));
329  printf("searching /opt3/aa : %d\n", XrdFfsDent_cache_search("/opt3","aa"));
330  printf("searching /opt4/aa : %d\n", XrdFfsDent_cache_search("/opt4","aa"));
331  printf("searching /opt5/aa : %d\n", XrdFfsDent_cache_search("/opt5","aa"));
332  XrdFfsDent_cache_destroy();
333  for (i=0; i<totdentnames; i++)
334  {
335  free(dnarray[i]);
336  }
337  free(dnarray);
338  exit(0);
339 }
340 */
341 
342 #ifdef __cplusplus
343  }
344 #endif
#define XrdFfsDent_NDENTCACHES
Definition: XrdFfsDent.cc:203
int XrdFfsDent_cache_search(char *dname, char *dentname)
Definition: XrdFfsDent.cc:247
int XrdFfsDent_dentcache_invalid(struct XrdFfsDentcache *cache)
Definition: XrdFfsDent.cc:176
unsigned int nents
Definition: XrdFfsDent.cc:135
void XrdFfsDent_cache_init()
Definition: XrdFfsDent.cc:207
struct XrdFfsDentcache XrdFfsDentCaches[XrdFfsDent_NDENTCACHES]
Definition: XrdFfsDent.cc:204
pthread_mutex_t XrdFfsDentCaches_mutex
Definition: XrdFfsDent.cc:205
void XrdFfsDent_names_del(struct XrdFfsDentnames **p)
Definition: XrdFfsDent.cc:49
void XrdFfsDent_names_join(struct XrdFfsDentnames **p, struct XrdFfsDentnames **n)
Definition: XrdFfsDent.cc:78
int XrdFfsDent_dentcache_search(struct XrdFfsDentcache *cache, char *dname, char *dentname)
Definition: XrdFfsDent.cc:183
int XrdFfsDent_dentcache_expired(struct XrdFfsDentcache *cache)
Definition: XrdFfsDent.cc:169
void XrdFfsDent_cache_destroy()
Definition: XrdFfsDent.cc:261
void XrdFfsDent_names_add(struct XrdFfsDentnames **p, char *name)
Definition: XrdFfsDent.cc:56
int XrdFfsDent_cache_fill(char *dname, char ***dnarray, int nents)
Definition: XrdFfsDent.cc:219
int XrdFfsDent_cstr_cmp(const void *a, const void *b)
Definition: XrdFfsDent.cc:39
void XrdFfsDent_dentcache_free(struct XrdFfsDentcache *cache)
Definition: XrdFfsDent.cc:154
int XrdFfsDent_names_extract(struct XrdFfsDentnames **p, char ***dnarray)
Definition: XrdFfsDent.cc:100
void XrdFfsDent_dentcache_fill(struct XrdFfsDentcache *cache, char *dname, char ***dnarray, int nents)
Definition: XrdFfsDent.cc:140
struct XrdFfsDentnames * next
Definition: XrdFfsDent.hh:41