XRootD
Loading...
Searching...
No Matches
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 */
39int 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
56void 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*/
100int 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
140void 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
183int 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);
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
205pthread_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
219int 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
247int 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
271main()
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
int XrdFfsDent_cache_search(char *dname, char *dentname)
int XrdFfsDent_dentcache_invalid(struct XrdFfsDentcache *cache)
unsigned int nents
void XrdFfsDent_cache_init()
struct XrdFfsDentcache XrdFfsDentCaches[XrdFfsDent_NDENTCACHES]
pthread_mutex_t XrdFfsDentCaches_mutex
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)
int XrdFfsDent_dentcache_expired(struct XrdFfsDentcache *cache)
void XrdFfsDent_cache_destroy()
void XrdFfsDent_names_add(struct XrdFfsDentnames **p, char *name)
Definition XrdFfsDent.cc:56
int XrdFfsDent_cache_fill(char *dname, char ***dnarray, int nents)
int XrdFfsDent_cstr_cmp(const void *a, const void *b)
Definition XrdFfsDent.cc:39
void XrdFfsDent_dentcache_free(struct XrdFfsDentcache *cache)
int XrdFfsDent_names_extract(struct XrdFfsDentnames **p, char ***dnarray)
void XrdFfsDent_dentcache_fill(struct XrdFfsDentcache *cache, char *dname, char ***dnarray, int nents)
struct XrdFfsDentnames * next
Definition XrdFfsDent.hh:41