2 Copyright (C) 2003 - 2010 Chaskiel Grundman
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
9 1. Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
12 2. Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
16 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 #include <afsconfig.h>
28 #include <afs/param.h>
34 #include <afs/vlserver.h>
35 #include <afs/vldbint.h>
37 #include "afscp_internal.h"
40 * Allocate and populate an afscp_venusfid struct from component parts
42 struct afscp_venusfid *
43 afscp_MakeFid(struct afscp_cell *cell, afs_uint32 volume,
44 afs_uint32 vnode, afs_uint32 unique)
46 struct afscp_venusfid *ret;
51 ret = malloc(sizeof(struct afscp_venusfid));
57 ret->fid.Volume = volume;
58 ret->fid.Vnode = vnode;
59 ret->fid.Unique = unique;
64 * Duplicate an existing afscp_venusfid struct
66 struct afscp_venusfid *
67 afscp_DupFid(const struct afscp_venusfid *in)
69 struct afscp_venusfid *ret;
71 ret = malloc(sizeof(struct afscp_venusfid));
77 ret->fid.Volume = in->fid.Volume;
78 ret->fid.Vnode = in->fid.Vnode;
79 ret->fid.Unique = in->fid.Unique;
84 afscp_FreeFid(struct afscp_venusfid *avfp)
91 statcompare(const void *a, const void *b)
93 const struct afscp_statent *sa = a, *sb = b;
94 if (sa->me.fid.Vnode < sb->me.fid.Vnode)
96 if (sa->me.fid.Vnode > sb->me.fid.Vnode)
98 if (sa->me.fid.Unique < sb->me.fid.Unique)
100 if (sa->me.fid.Unique > sb->me.fid.Unique)
106 _StatCleanup(struct afscp_statent *stored)
108 pthread_cond_destroy(&(stored->cv));
109 pthread_mutex_unlock(&(stored->mtx));
110 pthread_mutex_destroy(&(stored->mtx));
115 afscp_WaitForCallback(const struct afscp_venusfid *fid, int seconds)
118 struct afscp_volume *v;
119 struct afscp_statent *stored, key;
122 v = afscp_VolumeById(fid->cell, fid->fid.Volume);
126 memmove(&key.me, fid, sizeof(*fid));
128 cached = tfind(&key, &v->statcache, statcompare);
129 if (cached != NULL) {
133 stored = *(struct afscp_statent **)cached;
136 gettimeofday(&tv, NULL);
137 ts.tv_sec = tv.tv_sec + seconds;
141 pthread_mutex_lock(&(stored->mtx));
144 code = pthread_cond_timedwait(&(stored->cv), &(stored->mtx), &ts);
146 pthread_cond_wait(&(stored->cv), &(stored->mtx));
147 if ((stored->nwaiters == 1) && stored->cleanup)
148 _StatCleanup(stored);
151 pthread_mutex_unlock(&(stored->mtx));
153 if ((code == EINTR) || (code == ETIMEDOUT)) {
161 afscp_GetStatus(const struct afscp_venusfid *fid, struct AFSFetchStatus *s)
163 struct afscp_volume *v;
164 struct afscp_server *server;
165 struct AFSCallBack cb;
166 struct AFSVolSync vs;
167 struct AFSFid tf = fid->fid;
168 struct afscp_statent *stored, key;
173 v = afscp_VolumeById(fid->cell, fid->fid.Volume);
177 memset(&key, 0, sizeof(key));
178 memcpy(&key.me, fid, sizeof(*fid));
180 cached = tfind(&key, &v->statcache, statcompare);
181 if (cached != NULL) {
182 stored = *(struct afscp_statent **)cached;
183 pthread_mutex_lock(&(stored->mtx));
184 memmove(s, &stored->status, sizeof(*s));
185 afs_dprintf(("Stat %u.%lu.%lu.%lu returning cached result\n",
186 fid->cell->id, fid->fid.Volume, fid->fid.Vnode,
188 if (stored->nwaiters)
189 pthread_cond_broadcast(&(stored->cv));
190 pthread_mutex_unlock(&(stored->mtx));
195 for (i = 0; i < v->nservers; i++) {
196 server = afscp_ServerByIndex(v->servers[i]);
197 if (server && server->naddrs > 0) {
198 for (j = 0; j < server->naddrs; j++) {
200 code = RXAFS_FetchStatus(server->conns[j], &tf, s, &cb, &vs);
202 afscp_AddCallBack(server, &fid->fid, s, &cb, now); /* calls _StatStuff */
203 afs_dprintf(("Stat %d.%lu.%lu.%lu"
204 " ok: type %ld size %ld\n",
206 afs_printable_uint32_lu(fid->fid.Volume),
207 afs_printable_uint32_lu(fid->fid.Vnode),
208 afs_printable_uint32_lu(fid->fid.Unique),
209 afs_printable_int32_ld(s->FileType),
210 afs_printable_int32_ld(s->Length)));
221 afscp_Stat(const struct afscp_venusfid *fid, struct stat *s)
224 struct AFSFetchStatus status;
228 if (s == NULL || fid == NULL) {
229 fprintf(stderr, "NULL args given to afscp_Stat, cannot continue\n");
233 code = afscp_GetStatus(fid, &status);
238 if (status.FileType == File)
239 s->st_mode = S_IFREG;
240 else if (status.FileType == Directory)
241 s->st_mode = S_IFDIR;
243 else if (status.FileType == SymbolicLink)
244 s->st_mode = S_IFLNK;
245 /* a behavior needs to be defined on Windows */
248 afscp_errno = EINVAL;
251 s->st_mode |= (status.UnixModeBits & (~S_IFMT));
252 s->st_nlink = status.LinkCount;
253 s->st_size = status.Length;
254 s->st_uid = status.Owner;
255 /*s->st_blksize=status.SegSize; */
256 s->st_atime = s->st_mtime = status.ClientModTime;
257 s->st_ctime = status.ServerModTime;
258 s->st_gid = status.Group;
263 afscp_CheckCallBack(const struct afscp_venusfid *fid, const struct afscp_server *server, afs_uint32 *expiretime)
265 struct AFSFetchStatus status;
266 struct afscp_callback *cb = NULL;
270 if (expiretime == NULL || fid == NULL) {
271 fprintf(stderr, "NULL args given to afscp_CheckCallback, cannot continue\n");
277 code = afscp_GetStatus(fid, &status);
281 code = afscp_FindCallBack(fid, server, &cb);
287 *expiretime = cb->cb.ExpirationTime + cb->as_of - now;
294 _StatInvalidate(const struct afscp_venusfid *fid)
296 struct afscp_volume *v;
297 struct afscp_statent *stored, key;
300 v = afscp_VolumeById(fid->cell, fid->fid.Volume);
304 memmove(&key.me, fid, sizeof(*fid));
306 cached = tfind(&key, &v->statcache, statcompare);
307 if (cached != NULL) {
308 stored = *(struct afscp_statent **)cached;
309 pthread_mutex_lock(&(stored->mtx));
310 tdelete(&key, &v->statcache, statcompare);
311 if (stored->nwaiters) {
312 /* avoid blocking callback thread */
313 pthread_cond_broadcast(&(stored->cv));
316 _StatCleanup(stored);
317 pthread_mutex_unlock(&(stored->mtx));
323 _StatStuff(const struct afscp_venusfid *fid, const struct AFSFetchStatus *s)
325 struct afscp_volume *v;
326 struct afscp_statent key, *stored;
329 v = afscp_VolumeById(fid->cell, fid->fid.Volume);
333 memmove(&key.me, fid, sizeof(*fid));
335 cached = tsearch(&key, &v->statcache, statcompare);
336 if (cached != NULL) {
337 stored = malloc(sizeof(struct afscp_statent));
338 if (stored != NULL) {
339 pthread_mutex_init(&(stored->mtx), NULL);
340 pthread_cond_init(&(stored->cv), NULL);
341 stored->nwaiters = 0;
343 memmove(&stored->me, fid, sizeof(*fid));
344 memmove(&stored->status, s, sizeof(*s));
345 *(struct afscp_statent **)cached = stored;
347 tdelete(&key, &v->statcache, statcompare);
354 afscp_StoreStatus(const struct afscp_venusfid *fid, struct AFSStoreStatus *s)
356 struct afscp_volume *v;
357 struct afscp_server *server;
358 struct AFSVolSync vs;
359 struct AFSFetchStatus fst;
360 struct AFSFid tf = fid->fid;
363 v = afscp_VolumeById(fid->cell, fid->fid.Volume);
369 for (i = 0; i < v->nservers; i++) {
370 server = afscp_ServerByIndex(v->servers[i]);
371 if (server && server->naddrs > 0) {
372 for (j = 0; j < server->naddrs; j++) {
373 code = RXAFS_StoreStatus(server->conns[j], &tf, s, &fst, &vs);
375 _StatStuff(fid, &fst); /* calls _StatStuff */