~ubuntu-branches/ubuntu/vivid/cctools/vivid

« back to all changes in this revision

Viewing changes to chirp/src/chirp_reli.c

  • Committer: Bazaar Package Importer
  • Author(s): Michael Hanke
  • Date: 2011-05-07 09:05:00 UTC
  • Revision ID: james.westby@ubuntu.com-20110507090500-lqpmdtwndor6e7os
Tags: upstream-3.3.2
ImportĀ upstreamĀ versionĀ 3.3.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
Copyright (C) 2003-2004 Douglas Thain and the University of Wisconsin
 
3
Copyright (C) 2005- The University of Notre Dame
 
4
This software is distributed under the GNU General Public License.
 
5
See the file COPYING for details.
 
6
*/
 
7
 
 
8
#include "chirp_reli.h"
 
9
#include "chirp_protocol.h"
 
10
#include "chirp_client.h"
 
11
 
 
12
#include "macros.h"
 
13
#include "debug.h"
 
14
#include "full_io.h"
 
15
#include "sleeptools.h"
 
16
#include "hash_table.h"
 
17
#include "xmalloc.h"
 
18
#include "list.h"
 
19
 
 
20
#include <string.h>
 
21
#include <stdlib.h>
 
22
#include <errno.h>
 
23
#include <unistd.h>
 
24
#include <sys/stat.h>
 
25
 
 
26
#define MIN_DELAY 1
 
27
#define MAX_DELAY 60
 
28
 
 
29
struct chirp_file {
 
30
        char host[CHIRP_LINE_MAX];
 
31
        char path[CHIRP_LINE_MAX];
 
32
        struct chirp_stat info;
 
33
        INT64_T fd;
 
34
        INT64_T flags;
 
35
        INT64_T mode;
 
36
        INT64_T serial;
 
37
        INT64_T stale;
 
38
        char *buffer;
 
39
        INT64_T buffer_valid;
 
40
        INT64_T buffer_offset;
 
41
        INT64_T buffer_dirty;
 
42
};
 
43
 
 
44
struct hash_table *table = 0;
 
45
static int chirp_reli_blocksize = 65536;
 
46
 
 
47
INT64_T chirp_reli_blocksize_get()
 
48
{
 
49
        return chirp_reli_blocksize;
 
50
}
 
51
 
 
52
void    chirp_reli_blocksize_set( INT64_T bs )
 
53
{
 
54
        chirp_reli_blocksize = bs;
 
55
}
 
56
 
 
57
static struct chirp_client * connect_to_host( const char *host, time_t stoptime )
 
58
{
 
59
        struct chirp_client *c;
 
60
 
 
61
        if(!table) {
 
62
                table = hash_table_create(0,0);
 
63
                if(!table) return 0;
 
64
        }
 
65
 
 
66
        c = hash_table_lookup(table,host);
 
67
        if(c) return c;
 
68
        
 
69
        if(!strncmp(host,"CONDOR",6)) {
 
70
                c = chirp_client_connect_condor(stoptime);
 
71
        } else {
 
72
                c = chirp_client_connect(host,1,stoptime);
 
73
        }
 
74
 
 
75
        if(c) {
 
76
                hash_table_insert(table,host,c);
 
77
                return c;
 
78
        } else {
 
79
                return 0;
 
80
        }
 
81
}
 
82
 
 
83
static INT64_T connect_to_file( struct chirp_client *client, struct chirp_file *file, time_t stoptime )
 
84
{
 
85
        struct chirp_stat buf;
 
86
 
 
87
        if(file->stale) {
 
88
                errno = ESTALE;
 
89
                return -1;
 
90
        }
 
91
 
 
92
        if(chirp_client_serial(client)==file->serial) return 1;
 
93
 
 
94
        debug(D_CHIRP,"verifying: %s",file->path);
 
95
        file->fd = chirp_client_open(client,file->path,file->flags,file->mode,&buf,stoptime);
 
96
        file->serial = chirp_client_serial(client);
 
97
        if(file->fd>=0) {
 
98
                if(buf.cst_dev!=file->info.cst_dev) {
 
99
                        debug(D_CHIRP,"stale: device changed: %s",file->path);
 
100
                        file->stale = 1;
 
101
                        errno = ESTALE;
 
102
                        return 0;
 
103
                } else if(buf.cst_ino!=file->info.cst_ino) {
 
104
                        debug(D_CHIRP,"stale: inode changed: %s",file->path);
 
105
                        file->stale = 1;
 
106
                        errno = ESTALE;
 
107
                        return 0;
 
108
                } else if(buf.cst_rdev!=file->info.cst_rdev) {
 
109
                        debug(D_CHIRP,"stale: rdev changed: %s",file->path);
 
110
                        file->stale = 1;
 
111
                        errno = ESTALE;
 
112
                        return 0;
 
113
                } else {
 
114
                        debug(D_CHIRP,"uptodate: %s",file->path);
 
115
                        file->stale = 0;
 
116
                        return 1;
 
117
                }
 
118
        } else {
 
119
                if(errno!=ECONNRESET) {
 
120
                        debug(D_CHIRP,"stale: %s: %s",strerror(errno),file->path);
 
121
                        file->stale = 1;
 
122
                        errno = ESTALE;
 
123
                        return 0;
 
124
                }
 
125
        }
 
126
 
 
127
        return 1;
 
128
}
 
129
 
 
130
static void invalidate_host( const char *host )
 
131
{
 
132
        struct chirp_client *c;
 
133
        c = hash_table_remove(table,host);
 
134
        if(c) chirp_client_disconnect(c);
 
135
}
 
136
 
 
137
struct chirp_file * chirp_reli_open( const char *host, const char *path, INT64_T flags, INT64_T mode, time_t stoptime )
 
138
{
 
139
        struct chirp_file *file;
 
140
        INT64_T delay=0;
 
141
        INT64_T nexttry;
 
142
        INT64_T result;
 
143
        struct chirp_stat buf;
 
144
        time_t current;
 
145
 
 
146
        while(1) {
 
147
                struct chirp_client *client = connect_to_host(host,stoptime);
 
148
                if(client) {
 
149
                        result = chirp_client_open(client,path,flags,mode,&buf,stoptime);
 
150
                        if(result>=0) {
 
151
                                file = xxmalloc(sizeof(*file));
 
152
                                strcpy(file->host,host);
 
153
                                strcpy(file->path,path);
 
154
                                memcpy(&file->info,&buf,sizeof(buf));
 
155
                                file->fd = result;
 
156
                                file->flags = flags & ~(O_CREAT|O_TRUNC);
 
157
                                file->mode = mode;
 
158
                                file->serial = chirp_client_serial(client);
 
159
                                file->stale = 0;
 
160
                                file->buffer = malloc(chirp_reli_blocksize);
 
161
                                file->buffer_offset = 0;
 
162
                                file->buffer_valid = 0;
 
163
                                file->buffer_dirty = 0;
 
164
                                return file;
 
165
                        } else {
 
166
                                if(errno!=ECONNRESET) return 0;
 
167
                        }
 
168
                        invalidate_host(host);
 
169
                } else {
 
170
                        if(errno==ENOENT) return 0;
 
171
                }
 
172
                if(time(0)>=stoptime) {
 
173
                        errno = ECONNRESET;
 
174
                        return 0;
 
175
                }
 
176
                if(delay>=2) debug(D_NOTICE,"couldn't connect to %s: still trying...\n",host);
 
177
                debug(D_CHIRP,"couldn't talk to %s: %s\n",host,strerror(errno));
 
178
                current = time(0);
 
179
                nexttry = MIN(stoptime,current+delay);
 
180
                debug(D_CHIRP,"try again in %d seconds\n",nexttry-current);
 
181
                sleep_until(nexttry);
 
182
                if(delay==0) {
 
183
                        delay = 1;
 
184
                } else {
 
185
                        delay = MIN(delay*2,MAX_DELAY);
 
186
                }
 
187
        }
 
188
}
 
189
 
 
190
INT64_T chirp_reli_close( struct chirp_file *file, time_t stoptime )
 
191
{
 
192
        struct chirp_client *client = connect_to_host(file->host,stoptime);
 
193
        chirp_reli_flush(file,stoptime);
 
194
        if(client) {
 
195
                if(chirp_client_serial(client)==file->serial) {
 
196
                        chirp_client_close(client,file->fd,stoptime);
 
197
                }
 
198
        }
 
199
        free(file->buffer);
 
200
        free(file);
 
201
        return 0;
 
202
}
 
203
 
 
204
#define RETRY_FILE( ZZZ ) \
 
205
        INT64_T delay=0; \
 
206
        INT64_T nexttry; \
 
207
        INT64_T result; \
 
208
        time_t current; \
 
209
        while(1) { \
 
210
                struct chirp_client *client = connect_to_host(file->host,stoptime); \
 
211
                if(client) { \
 
212
                        if(connect_to_file(client,file,stoptime)) { \
 
213
                                ZZZ \
 
214
                                if(result>=0 || errno!=ECONNRESET) return result; \
 
215
                        } \
 
216
                        if(errno==ESTALE) return -1; \
 
217
                        invalidate_host(file->host); \
 
218
                } else { \
 
219
                        if(errno==ENOENT) return -1; \
 
220
                        if(errno==EPERM) return -1; \
 
221
                        if(errno==EACCES) return -1; \
 
222
                } \
 
223
                if(time(0)>=stoptime) { \
 
224
                        errno = ECONNRESET; \
 
225
                        return -1; \
 
226
                } \
 
227
                if(delay>=2) debug(D_NOTICE,"couldn't connect to %s: still trying...\n",file->host); \
 
228
                debug(D_CHIRP,"couldn't talk to %s: %s\n",file->host,strerror(errno)); \
 
229
                current = time(0); \
 
230
                nexttry = MIN(stoptime,current+delay); \
 
231
                debug(D_CHIRP,"try again in %d seconds\n",nexttry-current); \
 
232
                sleep_until(nexttry); \
 
233
                if(delay==0) {\
 
234
                        delay = 1;\
 
235
                } else {\
 
236
                        delay = MIN(delay*2,MAX_DELAY); \
 
237
                }\
 
238
        }
 
239
 
 
240
 
 
241
INT64_T chirp_reli_pread_unbuffered( struct chirp_file *file, void *data, INT64_T length, INT64_T offset, time_t stoptime )
 
242
{
 
243
        RETRY_FILE( result = chirp_client_pread(client,file->fd,data,length,offset,stoptime); )
 
244
}
 
245
 
 
246
static INT64_T chirp_reli_pread_buffered( struct chirp_file *file, void *data, INT64_T length, INT64_T offset, time_t stoptime )
 
247
{
 
248
        if(file->buffer_valid) {
 
249
                if(offset >= file->buffer_offset && offset < (file->buffer_offset+file->buffer_valid) ) {
 
250
                        INT64_T blength;
 
251
                        blength = MIN(length,file->buffer_offset+file->buffer_valid-offset);
 
252
                        memcpy(data,&file->buffer[offset-file->buffer_offset],blength);
 
253
                        return blength;
 
254
                }
 
255
        }
 
256
 
 
257
        chirp_reli_flush(file,stoptime);
 
258
 
 
259
        if(length<=chirp_reli_blocksize) {
 
260
                INT64_T result = chirp_reli_pread_unbuffered(file,file->buffer,chirp_reli_blocksize,offset,stoptime);
 
261
                if(result<0) {
 
262
                        file->buffer_offset = 0;
 
263
                        file->buffer_valid = 0;
 
264
                        file->buffer_dirty = 0;
 
265
                        return result;
 
266
                } else {
 
267
                        file->buffer_offset = offset;
 
268
                        file->buffer_valid = result;
 
269
                        file->buffer_dirty = 0;
 
270
                        result = MIN(result,length);
 
271
                        memcpy(data,file->buffer,result);
 
272
                        return result;
 
273
                }
 
274
        } else {
 
275
                return chirp_reli_pread_unbuffered(file,data,length,offset,stoptime);
 
276
        }
 
277
}
 
278
 
 
279
INT64_T chirp_reli_pread( struct chirp_file *file, void *data, INT64_T length, INT64_T offset, time_t stoptime )
 
280
{
 
281
        char *cdata = data;
 
282
        INT64_T result = 0;
 
283
        INT64_T actual = 0;
 
284
 
 
285
        while(length>0) {
 
286
                actual = chirp_reli_pread_buffered(file,cdata,length,offset,stoptime);
 
287
                if(actual<=0) break;
 
288
 
 
289
                result += actual;
 
290
                cdata += actual;
 
291
                offset += actual;
 
292
                length -= actual;
 
293
        }
 
294
 
 
295
        if(result>0) {
 
296
                return result;
 
297
        } else {
 
298
                return actual;
 
299
        }
 
300
}
 
301
 
 
302
INT64_T chirp_reli_pwrite_unbuffered( struct chirp_file *file, const void *data, INT64_T length, INT64_T offset, time_t stoptime )
 
303
{
 
304
        RETRY_FILE( result = chirp_client_pwrite(client,file->fd,data,length,offset,stoptime); )
 
305
}
 
306
 
 
307
static INT64_T chirp_reli_pwrite_buffered( struct chirp_file *file, const void *data, INT64_T length, INT64_T offset, time_t stoptime )
 
308
{
 
309
        if(length>=chirp_reli_blocksize) {
 
310
                if(chirp_reli_flush(file,stoptime)<0) {
 
311
                        return -1;
 
312
                } else {
 
313
                        return chirp_reli_pwrite_unbuffered(file,data,length,offset,stoptime);
 
314
                }
 
315
        }
 
316
 
 
317
        if(file->buffer_valid>0) {
 
318
                if( (file->buffer_offset + file->buffer_valid) == offset ) {
 
319
                        INT64_T blength = MIN(chirp_reli_blocksize-file->buffer_valid,length);
 
320
                        memcpy(&file->buffer[file->buffer_valid],data,blength);
 
321
                        file->buffer_valid += blength;
 
322
                        file->buffer_dirty = 1;
 
323
                        if(file->buffer_valid==chirp_reli_blocksize) {
 
324
                                if(chirp_reli_flush(file,stoptime)<0) {
 
325
                                        return -1;
 
326
                                }
 
327
                        }
 
328
                        return blength;
 
329
                } else {
 
330
                        if(chirp_reli_flush(file,stoptime)<0) {
 
331
                                return -1;
 
332
                        } else {
 
333
                                /* fall through */
 
334
                        }
 
335
                }
 
336
        }
 
337
 
 
338
        /* if we got here, then the buffer is empty */
 
339
 
 
340
        file->buffer_offset = offset;
 
341
        file->buffer_valid = length;
 
342
        file->buffer_dirty = 1;
 
343
        memcpy(file->buffer,data,length);
 
344
        return length;
 
345
}
 
346
 
 
347
INT64_T chirp_reli_pwrite( struct chirp_file *file, const void *data, INT64_T length, INT64_T offset, time_t stoptime )
 
348
{
 
349
        const char *cdata = data;
 
350
        INT64_T result = 0;
 
351
        INT64_T actual = 0;
 
352
 
 
353
        while(length>0) {
 
354
                actual = chirp_reli_pwrite_buffered(file,cdata,length,offset,stoptime);
 
355
                if(actual<=0) break;
 
356
 
 
357
                result += actual;
 
358
                cdata += actual;
 
359
                offset += actual;
 
360
                length -= actual;
 
361
        }
 
362
 
 
363
        if(result>0) {
 
364
                return result;
 
365
        } else {
 
366
                return actual;
 
367
        }
 
368
}
 
369
 
 
370
INT64_T chirp_reli_sread( struct chirp_file *file, void *data, INT64_T length, INT64_T stride_length, INT64_T stride_offset, INT64_T offset, time_t stoptime )
 
371
{
 
372
        chirp_reli_flush(file,stoptime);
 
373
        RETRY_FILE( result = chirp_client_sread(client,file->fd,data,length,stride_length,stride_offset,offset,stoptime); )
 
374
}
 
375
 
 
376
INT64_T chirp_reli_swrite( struct chirp_file *file, const void *data, INT64_T length, INT64_T stride_length, INT64_T stride_offset, INT64_T offset, time_t stoptime )
 
377
{
 
378
        chirp_reli_flush(file,stoptime);
 
379
        RETRY_FILE( result = chirp_client_swrite(client,file->fd,data,length,stride_length,stride_offset,offset,stoptime); )
 
380
}
 
381
 
 
382
INT64_T chirp_reli_fstat( struct chirp_file *file, struct chirp_stat *buf, time_t stoptime )
 
383
{
 
384
        chirp_reli_flush(file,stoptime);
 
385
        RETRY_FILE( result = chirp_client_fstat(client,file->fd,buf,stoptime); )
 
386
}
 
387
 
 
388
INT64_T chirp_reli_fstatfs( struct chirp_file *file, struct chirp_statfs *buf, time_t stoptime )
 
389
{
 
390
        chirp_reli_flush(file,stoptime);
 
391
        RETRY_FILE( result = chirp_client_fstatfs(client,file->fd,buf,stoptime); )
 
392
}
 
393
 
 
394
INT64_T chirp_reli_fchown( struct chirp_file *file, INT64_T uid, INT64_T gid, time_t stoptime )
 
395
{
 
396
        chirp_reli_flush(file,stoptime);
 
397
        RETRY_FILE( result = chirp_client_fchown(client,file->fd,uid,gid,stoptime); )
 
398
}
 
399
 
 
400
INT64_T chirp_reli_fchmod( struct chirp_file *file, INT64_T mode, time_t stoptime )
 
401
{
 
402
        chirp_reli_flush(file,stoptime);
 
403
        RETRY_FILE( result = chirp_client_fchmod(client,file->fd,mode,stoptime); )
 
404
}
 
405
 
 
406
INT64_T chirp_reli_ftruncate( struct chirp_file *file, INT64_T length, time_t stoptime )
 
407
{
 
408
        chirp_reli_flush(file,stoptime);
 
409
        RETRY_FILE( result = chirp_client_ftruncate(client,file->fd,length,stoptime); )
 
410
}
 
411
 
 
412
INT64_T chirp_reli_flush( struct chirp_file *file, time_t stoptime )
 
413
{
 
414
        INT64_T result;
 
415
 
 
416
        if(file->buffer_valid && file->buffer_dirty) {
 
417
                result = chirp_reli_pwrite_unbuffered(file,file->buffer,file->buffer_valid,file->buffer_offset,stoptime);
 
418
        } else {
 
419
                result = 0;
 
420
        }
 
421
 
 
422
        file->buffer_valid = 0;
 
423
        file->buffer_dirty = 0;
 
424
        file->buffer_offset = 0;
 
425
 
 
426
        return result;
 
427
}
 
428
 
 
429
INT64_T chirp_reli_fsync( struct chirp_file *file, time_t stoptime )
 
430
{
 
431
        chirp_reli_flush(file,stoptime);
 
432
        RETRY_FILE( result = chirp_client_fsync(client,file->fd,stoptime); );
 
433
}
 
434
 
 
435
#define RETRY_ATOMIC( ZZZ ) \
 
436
        INT64_T delay=0; \
 
437
        INT64_T nexttry; \
 
438
        INT64_T result; \
 
439
        time_t current; \
 
440
        while(1) { \
 
441
                struct chirp_client *client = connect_to_host(host,stoptime); \
 
442
                if(client) { \
 
443
                        ZZZ \
 
444
                        if(result>=0 || errno!=ECONNRESET) return result; \
 
445
                        invalidate_host(host); \
 
446
                } else { \
 
447
                        if(errno==ENOENT) return -1; \
 
448
                        if(errno==EPERM) return -1; \
 
449
                        if(errno==EACCES) return -1; \
 
450
                } \
 
451
                if(time(0)>=stoptime) { \
 
452
                        errno = ECONNRESET; \
 
453
                        return -1; \
 
454
                } \
 
455
                if(delay>=2) debug(D_NOTICE,"couldn't connect to %s: still trying...\n",host); \
 
456
                debug(D_CHIRP,"couldn't talk to %s: %s\n",host,strerror(errno)); \
 
457
                current = time(0); \
 
458
                nexttry = MIN(stoptime,current+delay); \
 
459
                debug(D_CHIRP,"try again in %d seconds\n",nexttry-current); \
 
460
                sleep_until(nexttry); \
 
461
                if(delay==0) {\
 
462
                        delay = 1;\
 
463
                } else {\
 
464
                        delay = MIN(delay*2,MAX_DELAY); \
 
465
                }\
 
466
        }
 
467
 
 
468
INT64_T chirp_reli_whoami( const char *host, char *buf, INT64_T length, time_t stoptime )
 
469
{
 
470
        RETRY_ATOMIC( result = chirp_client_whoami(client,buf,length,stoptime); );
 
471
}
 
472
 
 
473
INT64_T chirp_reli_whoareyou( const char *host, const char *rhost, char *buffer, INT64_T length, time_t stoptime  )
 
474
{
 
475
        RETRY_ATOMIC( result = chirp_client_whoareyou(client,rhost,buffer,length,stoptime); );
 
476
}
 
477
 
 
478
INT64_T chirp_reli_getfile( const char *host, const char *path, FILE *stream, time_t stoptime )
 
479
{
 
480
        INT64_T pos = ftell(stream);
 
481
        if (pos < 0) pos = 0;
 
482
 
 
483
        RETRY_ATOMIC(\
 
484
                fseek(stream,pos,SEEK_SET);\
 
485
                result = chirp_client_getfile(client,path,stream,stoptime);\
 
486
                if(result<0 && ferror(stream)) { errno=EIO; return -1; }\
 
487
        )
 
488
}
 
489
 
 
490
INT64_T chirp_reli_getfile_buffer( const char *host, const char *path, char **buffer, time_t stoptime )
 
491
{
 
492
        RETRY_ATOMIC( result = chirp_client_getfile_buffer(client,path,buffer,stoptime); )
 
493
}
 
494
 
 
495
INT64_T chirp_reli_putfile( const char *host, const char *path, FILE *stream, INT64_T mode, INT64_T length, time_t stoptime )
 
496
{
 
497
        RETRY_ATOMIC(
 
498
                fseek(stream,0,SEEK_SET);\
 
499
                result = chirp_client_putfile(client,path,stream,mode,length,stoptime);\
 
500
                if(result<0 && ferror(stream)) { errno=EIO; return -1; }\
 
501
        )
 
502
}
 
503
 
 
504
INT64_T chirp_reli_putfile_buffer( const char *host, const char *path, const char *buffer, INT64_T mode, INT64_T length, time_t stoptime )
 
505
{
 
506
        RETRY_ATOMIC( result = chirp_client_putfile_buffer(client,path,buffer,mode,length,stoptime); )
 
507
}
 
508
 
 
509
INT64_T chirp_reli_getlongdir( const char *host, const char *path, chirp_longdir_t callback, void *arg, time_t stoptime )
 
510
{
 
511
        RETRY_ATOMIC( result = chirp_client_getlongdir(client,path,callback,arg,stoptime); )
 
512
}
 
513
 
 
514
INT64_T chirp_reli_getdir( const char *host, const char *path, chirp_dir_t callback, void *arg, time_t stoptime )
 
515
{
 
516
        RETRY_ATOMIC( result = chirp_client_getdir(client,path,callback,arg,stoptime); )
 
517
}
 
518
 
 
519
INT64_T chirp_reli_getacl( const char *host, const char *path, chirp_dir_t callback, void *arg, time_t stoptime )
 
520
{
 
521
        RETRY_ATOMIC( result = chirp_client_getacl(client,path,callback,arg,stoptime); )
 
522
}
 
523
 
 
524
INT64_T chirp_reli_ticket_create( const char *host, char name[CHIRP_PATH_MAX], unsigned bits, time_t stoptime )
 
525
{
 
526
        RETRY_ATOMIC( result = chirp_client_ticket_create(client,name,bits,stoptime); )
 
527
}
 
528
 
 
529
INT64_T chirp_reli_ticket_register( const char *host, const char *name, const char *subject, time_t duration, time_t stoptime )
 
530
{
 
531
        RETRY_ATOMIC( result = chirp_client_ticket_register(client,name,subject,duration,stoptime); )
 
532
}
 
533
 
 
534
INT64_T chirp_reli_ticket_delete( const char *host, const char *name, time_t stoptime )
 
535
{
 
536
        RETRY_ATOMIC( result = chirp_client_ticket_delete(client,name,stoptime); )
 
537
}
 
538
 
 
539
INT64_T chirp_reli_ticket_list( const char *host, const char *subject, char ***list, time_t stoptime )
 
540
{
 
541
        RETRY_ATOMIC( result = chirp_client_ticket_list(client,subject,list,stoptime); )
 
542
}
 
543
 
 
544
INT64_T chirp_reli_ticket_get( const char *host, const char *name, char **subject, char **ticket, time_t *duration, char ***rights, time_t stoptime )
 
545
{
 
546
        RETRY_ATOMIC( result = chirp_client_ticket_get(client,name,subject,ticket,duration,rights,stoptime); )
 
547
}
 
548
 
 
549
INT64_T chirp_reli_ticket_modify( const char *host, const char *name, const char *path, const char *aclmask, time_t stoptime )
 
550
{
 
551
        RETRY_ATOMIC( result = chirp_client_ticket_modify(client,name,path,aclmask,stoptime); )
 
552
}
 
553
 
 
554
INT64_T chirp_reli_setacl( const char *host, const char *path, const char *subject, const char *rights, time_t stoptime )
 
555
{
 
556
        RETRY_ATOMIC( result = chirp_client_setacl(client,path,subject,rights,stoptime); )
 
557
}
 
558
 
 
559
INT64_T chirp_reli_resetacl( const char *host, const char *path, const char *rights, time_t stoptime )
 
560
{
 
561
        RETRY_ATOMIC( result = chirp_client_resetacl(client,path,rights,stoptime); )
 
562
}
 
563
 
 
564
INT64_T chirp_reli_locate( const char *host, const char *path, chirp_loc_t callback, void *arg, time_t stoptime )
 
565
{
 
566
        RETRY_ATOMIC( result = chirp_client_locate(client,path,callback,arg,stoptime); )
 
567
}
 
568
 
 
569
INT64_T chirp_reli_unlink( const char *host, const char *path, time_t stoptime )
 
570
{
 
571
        RETRY_ATOMIC( result = chirp_client_unlink(client,path,stoptime); )
 
572
}
 
573
 
 
574
INT64_T chirp_reli_rename( const char *host, const char *path, const char *newpath, time_t stoptime )
 
575
{
 
576
        RETRY_ATOMIC( result = chirp_client_rename(client,path,newpath,stoptime); )
 
577
}
 
578
 
 
579
INT64_T chirp_reli_link( const char *host, const char *path, const char *newpath, time_t stoptime )
 
580
{
 
581
        RETRY_ATOMIC( result = chirp_client_link(client,path,newpath,stoptime); )
 
582
}
 
583
 
 
584
INT64_T chirp_reli_symlink( const char *host, const char *path, const char *newpath, time_t stoptime )
 
585
{
 
586
        RETRY_ATOMIC( result = chirp_client_symlink(client,path,newpath,stoptime); )
 
587
}
 
588
 
 
589
INT64_T chirp_reli_readlink( const char *host, const char *path, char *buf, INT64_T length, time_t stoptime )
 
590
{
 
591
        RETRY_ATOMIC( result = chirp_client_readlink(client,path,buf,length,stoptime); )
 
592
}
 
593
 
 
594
INT64_T chirp_reli_mkdir( const char *host, const char *path, INT64_T mode, time_t stoptime )
 
595
{
 
596
        RETRY_ATOMIC( result = chirp_client_mkdir(client,path,mode,stoptime); )
 
597
}
 
598
 
 
599
INT64_T chirp_reli_mkdir_recursive( const char *host, const char *path, INT64_T mode, time_t stoptime )
 
600
{
 
601
        char mypath[CHIRP_PATH_MAX];
 
602
        strcpy(mypath,path);
 
603
 
 
604
        char *n = strchr(&mypath[1],'/');
 
605
        while(n) {
 
606
                *n = 0;
 
607
                /* ignore the result here, because there are many reasons we might not have permission to make or view directories above. */
 
608
                chirp_reli_mkdir(host,mypath,mode,stoptime);
 
609
                *n = '/';
 
610
                n = strchr(n+1,'/');
 
611
        }
 
612
 
 
613
        /* this is the error that really counts */
 
614
        return chirp_reli_mkdir(host,path,mode,stoptime);
 
615
}
 
616
 
 
617
INT64_T chirp_reli_rmdir( const char *host, const char *path, time_t stoptime )
 
618
{
 
619
        RETRY_ATOMIC( result = chirp_client_rmdir(client,path,stoptime); )
 
620
}
 
621
 
 
622
INT64_T chirp_reli_rmall( const char *host, const char *path, time_t stoptime )
 
623
{
 
624
        RETRY_ATOMIC( result = chirp_client_rmall(client,path,stoptime); )
 
625
}
 
626
 
 
627
INT64_T chirp_reli_stat( const char *host, const char *path, struct chirp_stat *buf, time_t stoptime )
 
628
{
 
629
        RETRY_ATOMIC( result = chirp_client_stat(client,path,buf,stoptime); )
 
630
}
 
631
 
 
632
INT64_T chirp_reli_lstat( const char *host, const char *path, struct chirp_stat *buf, time_t stoptime )
 
633
{
 
634
        RETRY_ATOMIC( result = chirp_client_lstat(client,path,buf,stoptime); )
 
635
}
 
636
 
 
637
INT64_T chirp_reli_statfs( const char *host, const char *path, struct chirp_statfs *buf, time_t stoptime )
 
638
{
 
639
        RETRY_ATOMIC( result = chirp_client_statfs(client,path,buf,stoptime); )
 
640
}
 
641
 
 
642
INT64_T chirp_reli_access( const char *host, const char *path, INT64_T mode, time_t stoptime )
 
643
{
 
644
        RETRY_ATOMIC( result = chirp_client_access(client,path,mode,stoptime); )
 
645
}
 
646
 
 
647
INT64_T chirp_reli_chmod( const char *host, const char *path, INT64_T mode, time_t stoptime )
 
648
{
 
649
        RETRY_ATOMIC( result = chirp_client_chmod(client,path,mode,stoptime); )
 
650
}
 
651
 
 
652
INT64_T chirp_reli_chown( const char *host, const char *path, INT64_T uid, INT64_T gid, time_t stoptime )
 
653
{
 
654
        RETRY_ATOMIC( result = chirp_client_chown(client,path,uid,gid,stoptime); )
 
655
}
 
656
 
 
657
INT64_T chirp_reli_lchown( const char *host, const char *path, INT64_T uid, INT64_T gid, time_t stoptime )
 
658
{
 
659
        RETRY_ATOMIC( result = chirp_client_lchown(client,path,uid,gid,stoptime); )
 
660
}
 
661
 
 
662
INT64_T chirp_reli_truncate( const char *host, const char *path, INT64_T length, time_t stoptime )
 
663
{
 
664
        RETRY_ATOMIC( result = chirp_client_truncate(client,path,length,stoptime); )
 
665
}
 
666
 
 
667
INT64_T chirp_reli_utime( const char *host, const char *path, time_t actime, time_t modtime, time_t stoptime )
 
668
{
 
669
        RETRY_ATOMIC( result = chirp_client_utime(client,path,actime,modtime,stoptime); )
 
670
}
 
671
 
 
672
INT64_T chirp_reli_md5( const char *host, const char *path, unsigned char digest[16], time_t stoptime )
 
673
{
 
674
        RETRY_ATOMIC( result = chirp_client_md5(client,path,digest,stoptime); )
 
675
}
 
676
 
 
677
INT64_T chirp_reli_localpath( const char *host, const char *path, char *localpath, int length, time_t stoptime )
 
678
{
 
679
        RETRY_ATOMIC( result = chirp_client_localpath(client,path,localpath,length,stoptime); )
 
680
}
 
681
 
 
682
INT64_T chirp_reli_audit( const char *host, const char *path, struct chirp_audit **list, time_t stoptime )
 
683
{
 
684
        RETRY_ATOMIC( result = chirp_client_audit(client,path,list,stoptime); )
 
685
}
 
686
 
 
687
INT64_T chirp_reli_thirdput( const char *host, const char *path, const char *thirdhost, const char *thirdpath, time_t stoptime )
 
688
{
 
689
        RETRY_ATOMIC( result = chirp_client_thirdput( client, path, thirdhost, thirdpath, stoptime ); )
 
690
}
 
691
 
 
692
INT64_T chirp_reli_group_create( const char *host, char *group, time_t stoptime )
 
693
{
 
694
        RETRY_ATOMIC ( result = chirp_client_group_create(client,group,stoptime); )
 
695
}
 
696
 
 
697
INT64_T chirp_reli_group_list( const char *host, const char *group, chirp_dir_t callback, void *arg, time_t stoptime )
 
698
{
 
699
        RETRY_ATOMIC ( result = chirp_client_group_list(client,group,callback,arg,stoptime); )
 
700
}
 
701
 
 
702
INT64_T chirp_reli_group_add( const char *host, char *group, char *user, time_t stoptime )
 
703
{
 
704
        RETRY_ATOMIC ( result = chirp_client_group_add(client,group,user,stoptime); )
 
705
}
 
706
 
 
707
INT64_T chirp_reli_group_remove( const char *host, char *group, char *user, time_t stoptime )
 
708
{
 
709
        RETRY_ATOMIC ( result = chirp_client_group_remove(client,group,user,stoptime); )
 
710
}
 
711
 
 
712
INT64_T chirp_reli_group_lookup(const char* host, const char* group, const char* user, time_t stoptime)
 
713
{
 
714
        RETRY_ATOMIC( result = chirp_client_group_lookup( client, group, user, stoptime ); )
 
715
}
 
716
 
 
717
INT64_T chirp_reli_group_policy_set( const char *host, char *group, unsigned long int file_duration, unsigned long int dec_duration, time_t stoptime )
 
718
{
 
719
        RETRY_ATOMIC ( result = chirp_client_group_policy_set(client,group,file_duration,dec_duration,stoptime); )
 
720
}
 
721
 
 
722
INT64_T chirp_reli_group_cache_update( const char* host, const char* group, time_t mod_time, time_t stoptime )
 
723
{
 
724
        RETRY_ATOMIC( result = chirp_client_group_cache_update( client, group, mod_time, stoptime ); )
 
725
 
726
 
 
727
INT64_T chirp_reli_group_policy_get(const char* host, const char* group, int* policy, int* file_duration, int* dec_duration, time_t stoptime)
 
728
{
 
729
        RETRY_ATOMIC( result = chirp_client_group_policy_get( client, group, policy, file_duration, dec_duration, stoptime ); )
 
730
}
 
731
 
 
732
INT64_T chirp_reli_mkalloc( const char *host, const char *path, INT64_T size, INT64_T mode, time_t stoptime )
 
733
{
 
734
        RETRY_ATOMIC( result = chirp_client_mkalloc(client,path,size,mode,stoptime); )
 
735
}
 
736
 
 
737
INT64_T chirp_reli_lsalloc( const char *host, const char *path, char *allocpath, INT64_T *total, INT64_T *inuse, time_t stoptime )
 
738
{
 
739
        RETRY_ATOMIC( result = chirp_client_lsalloc(client,path,allocpath,total,inuse,stoptime); )
 
740
}
 
741
 
 
742
INT64_T chirp_reli_job_begin( const char *host, const char *cwd, const char *input, const char *output, const char *error, const char *cmdline, time_t stoptime )
 
743
{
 
744
        RETRY_ATOMIC( result = chirp_client_job_begin(client,cwd,input,output,error,cmdline,stoptime); )
 
745
}
 
746
 
 
747
INT64_T chirp_reli_job_commit( const char *host, INT64_T jobid, time_t stoptime )
 
748
{
 
749
        RETRY_ATOMIC( result = chirp_client_job_commit(client,jobid,stoptime); );
 
750
}
 
751
 
 
752
INT64_T chirp_reli_job_wait( const char *host, INT64_T jobid, struct chirp_job_state *state, int wait_time, time_t stoptime )
 
753
{
 
754
        RETRY_ATOMIC( result = chirp_client_job_wait(client,jobid,state,wait_time,stoptime); );
 
755
}
 
756
 
 
757
INT64_T chirp_reli_job_kill( const char *host, INT64_T jobid, time_t stoptime )
 
758
{
 
759
        RETRY_ATOMIC( result = chirp_client_job_kill(client,jobid,stoptime); );
 
760
}
 
761
 
 
762
INT64_T chirp_reli_job_remove( const char *host, INT64_T jobid, time_t stoptime )
 
763
{
 
764
        RETRY_ATOMIC( result = chirp_client_job_remove(client,jobid,stoptime); );
 
765
}
 
766
 
 
767
INT64_T chirp_reli_job_list( const char *host, chirp_joblist_t callback, void *arg, time_t stoptime )
 
768
{
 
769
        RETRY_ATOMIC( result = chirp_client_job_list(client,callback,arg,stoptime); );
 
770
}
 
771
 
 
772
struct chirp_dir {
 
773
       struct chirp_dirent *head;
 
774
       struct chirp_dirent *current;
 
775
};
 
776
 
 
777
static void opendir_callback( const char *path, struct chirp_stat *info, void *vdir )
 
778
{
 
779
        struct chirp_dir *dir = vdir;
 
780
        struct chirp_dirent *d;
 
781
 
 
782
        d = malloc(sizeof(*d));
 
783
        d->name = strdup(path);
 
784
        d->info = *info;
 
785
        d->next = 0;
 
786
 
 
787
        if(!dir->head) {
 
788
                dir->head = d;
 
789
                dir->current = d;
 
790
        } else {
 
791
                dir->current->next = d;
 
792
                dir->current = d;
 
793
        }
 
794
}
 
795
 
 
796
struct chirp_dir * chirp_reli_opendir( const char *host, const char *path, time_t stoptime )
 
797
{
 
798
        struct chirp_dir *dir = malloc(sizeof(*dir));
 
799
        INT64_T result;
 
800
 
 
801
        dir->head = dir->current = 0;
 
802
 
 
803
        result = chirp_reli_getlongdir(host,path,opendir_callback,dir,stoptime);
 
804
        if(result<0) {
 
805
                chirp_reli_closedir(dir);
 
806
                return 0;
 
807
        }
 
808
 
 
809
        dir->current = dir->head;
 
810
 
 
811
        return dir;
 
812
}
 
813
 
 
814
struct chirp_dirent * chirp_reli_readdir( struct chirp_dir *dir )
 
815
{
 
816
        struct chirp_dirent *d;
 
817
 
 
818
        if(!dir) return 0;
 
819
 
 
820
        d = dir->current;
 
821
        if(d) dir->current = dir->current->next;
 
822
 
 
823
        return d;
 
824
}
 
825
 
 
826
void chirp_reli_closedir( struct chirp_dir *dir )
 
827
{
 
828
        struct chirp_dirent *next;
 
829
 
 
830
        if(!dir) return;
 
831
 
 
832
        while(dir->head) {
 
833
                next = dir->head->next;
 
834
                free(dir->head->name);
 
835
                free(dir->head);
 
836
                dir->head = next;
 
837
        }
 
838
        free(dir);
 
839
}
 
840
 
 
841
static INT64_T chirp_reli_bulkio_once( struct chirp_bulkio *v, int count, time_t stoptime )
 
842
{
 
843
        int i;
 
844
        INT64_T result;
 
845
 
 
846
        for(i=0;i<count;i++) {
 
847
                struct chirp_bulkio *b = &v[i];
 
848
                struct chirp_client *client;
 
849
 
 
850
                client = connect_to_host(b->file->host,stoptime);
 
851
                if(!client) goto failure;
 
852
 
 
853
                if(connect_to_file(client,b->file,stoptime)<0) goto failure;
 
854
 
 
855
                if(b->type==CHIRP_BULKIO_PREAD) {
 
856
                        result = chirp_client_pread_begin(client,b->file->fd,b->buffer,b->length,b->offset,stoptime);
 
857
                } else if(b->type==CHIRP_BULKIO_PWRITE) {
 
858
                        result = chirp_client_pwrite_begin(client,b->file->fd,b->buffer,b->length,b->offset,stoptime);
 
859
                } else if(b->type==CHIRP_BULKIO_SREAD) {
 
860
                        result = chirp_client_sread_begin(client,b->file->fd,b->buffer,b->length,b->stride_length,b->stride_skip,b->offset,stoptime);
 
861
                } else if(b->type==CHIRP_BULKIO_SWRITE) {
 
862
                        result = chirp_client_swrite_begin(client,b->file->fd,b->buffer,b->length,b->stride_length,b->stride_skip,b->offset,stoptime);
 
863
                } else if(b->type==CHIRP_BULKIO_FSTAT) {
 
864
                        result = chirp_client_fstat_begin(client,b->file->fd,b->info,stoptime);
 
865
                } else if(b->type==CHIRP_BULKIO_FSYNC) {
 
866
                        result = chirp_client_fsync_begin(client,b->file->fd,stoptime);
 
867
                } else {
 
868
                        result = -1;
 
869
                        errno = EINVAL;
 
870
                }
 
871
 
 
872
                if(result<0 && errno==ECONNRESET) goto failure;
 
873
        }
 
874
 
 
875
        for(i=0;i<count;i++) {
 
876
                struct chirp_bulkio *b = &v[i];
 
877
                struct chirp_client *client;
 
878
 
 
879
                client = connect_to_host(b->file->host,stoptime);
 
880
                if(!client) goto failure;
 
881
 
 
882
                if(b->type==CHIRP_BULKIO_PREAD) {
 
883
                        result = chirp_client_pread_finish(client,b->file->fd,b->buffer,b->length,b->offset,stoptime);
 
884
                } else if(b->type==CHIRP_BULKIO_PWRITE) {
 
885
                        result = chirp_client_pwrite_finish(client,b->file->fd,b->buffer,b->length,b->offset,stoptime);
 
886
                } else if(b->type==CHIRP_BULKIO_SREAD) {
 
887
                        result = chirp_client_sread_finish(client,b->file->fd,b->buffer,b->length,b->stride_length,b->stride_skip,b->offset,stoptime);
 
888
                } else if(b->type==CHIRP_BULKIO_SWRITE) {
 
889
                        result = chirp_client_swrite_finish(client,b->file->fd,b->buffer,b->length,b->stride_length,b->stride_skip,b->offset,stoptime);
 
890
                } else if(b->type==CHIRP_BULKIO_FSTAT) {
 
891
                        result = chirp_client_fstat_finish(client,b->file->fd,b->info,stoptime);
 
892
                } else if(b->type==CHIRP_BULKIO_FSYNC) {
 
893
                        result = chirp_client_fsync_finish(client,b->file->fd,stoptime);
 
894
                } else {
 
895
                        result = -1;
 
896
                        errno = EINVAL;
 
897
                }
 
898
 
 
899
                if(result<0 && errno==ECONNRESET) goto failure;
 
900
 
 
901
                b->result = result;
 
902
                b->errnum = errno;
 
903
        }
 
904
 
 
905
        return count;
 
906
 
 
907
        failure:
 
908
        for(i=0;i<count;i++) {
 
909
                struct chirp_bulkio *b = &v[i];
 
910
                invalidate_host(b->file->host);
 
911
        }
 
912
        errno = ECONNRESET;
 
913
        return -1;
 
914
}
 
915
 
 
916
INT64_T chirp_reli_bulkio( struct chirp_bulkio *v, int count, time_t stoptime )
 
917
{
 
918
        INT64_T delay=0;
 
919
        INT64_T nexttry;
 
920
        INT64_T result;
 
921
        time_t current;
 
922
 
 
923
        while(1) {
 
924
                result = chirp_reli_bulkio_once(v,count,stoptime);
 
925
 
 
926
                if(result>=0 || errno!=ECONNRESET) return result;
 
927
 
 
928
                if(time(0)>=stoptime) {
 
929
                        errno = ECONNRESET;
 
930
                        return -1;
 
931
                }
 
932
                if(delay>=2) debug(D_NOTICE,"couldn't connect: still trying...\n");
 
933
                current = time(0);
 
934
                nexttry = MIN(stoptime,current+delay);
 
935
                debug(D_CHIRP,"try again in %d seconds\n",nexttry-current);
 
936
                sleep_until(nexttry);
 
937
                if(delay==0) {
 
938
                        delay = 1;
 
939
                } else {
 
940
                        delay = MIN(delay*2,MAX_DELAY);
 
941
                }
 
942
        }
 
943
}
 
944
 
 
945
void chirp_reli_cleanup_before_fork()
 
946
{
 
947
        char *host;
 
948
        char *value;
 
949
 
 
950
        if(!table) return;
 
951
 
 
952
        hash_table_firstkey(table);
 
953
        while(hash_table_nextkey(table,&host,(void**)&value)) {
 
954
                invalidate_host(host);
 
955
        }               
 
956
}
 
957
 
 
958