~ubuntu-branches/ubuntu/utopic/nwchem/utopic

« back to all changes in this revision

Viewing changes to src/tools/ga-5-2/pario/elio/elio.c

  • Committer: Package Import Robot
  • Author(s): Michael Banck, Daniel Leidert, Andreas Tille, Michael Banck
  • Date: 2013-07-04 12:14:55 UTC
  • mfrom: (1.1.2)
  • Revision ID: package-import@ubuntu.com-20130704121455-5tvsx2qabor3nrui
Tags: 6.3-1
* New upstream release.
* Fixes anisotropic properties (Closes: #696361).
* New features include:
  + Multi-reference coupled cluster (MRCC) approaches
  + Hybrid DFT calculations with short-range HF 
  + New density-functionals including Minnesota (M08, M11) and HSE hybrid
    functionals
  + X-ray absorption spectroscopy (XAS) with TDDFT
  + Analytical gradients for the COSMO solvation model
  + Transition densities from TDDFT 
  + DFT+U and Electron-Transfer (ET) methods for plane wave calculations
  + Exploitation of space group symmetry in plane wave geometry optimizations
  + Local density of states (LDOS) collective variable added to Metadynamics
  + Various new XC functionals added for plane wave calculations, including
    hybrid and range-corrected ones
  + Electric field gradients with relativistic corrections 
  + Nudged Elastic Band optimization method
  + Updated basis sets and ECPs 

[ Daniel Leidert ]
* debian/watch: Fixed.

[ Andreas Tille ]
* debian/upstream: References

[ Michael Banck ]
* debian/upstream (Name): New field.
* debian/patches/02_makefile_flags.patch: Refreshed.
* debian/patches/06_statfs_kfreebsd.patch: Likewise.
* debian/patches/07_ga_target_force_linux.patch: Likewise.
* debian/patches/05_avoid_inline_assembler.patch: Removed, no longer needed.
* debian/patches/09_backported_6.1.1_fixes.patch: Likewise.
* debian/control (Build-Depends): Added gfortran-4.7 and gcc-4.7.
* debian/patches/10_force_gcc-4.7.patch: New patch, explicitly sets
  gfortran-4.7 and gcc-4.7, fixes test suite hang with gcc-4.8 (Closes:
  #701328, #713262).
* debian/testsuite: Added tests for COSMO analytical gradients and MRCC.
* debian/rules (MRCC_METHODS): New variable, required to enable MRCC methods.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#if HAVE_CONFIG_H
 
2
#   include "config.h"
 
3
#endif
 
4
 
 
5
/** @file
 
6
 **********************************************************************\
 
7
 ELementary I/O (ELIO) disk operations for parallel I/O libraries   
 
8
 Authors: Jarek Nieplocha (PNNL) and Jace Mogill (ANL)
 
9
 *
 
10
 * DISCLAIMER
 
11
 *
 
12
 * This material was prepared as an account of work sponsored by an
 
13
 * agency of the United States Government.  Neither the United States
 
14
 * Government nor the United States Department of Energy, nor Battelle,
 
15
 * nor any of their employees, MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR
 
16
 * ASSUMES ANY LEGAL LIABILITY OR RESPONSIBILITY FOR THE ACCURACY,
 
17
 * COMPLETENESS, OR USEFULNESS OF ANY INFORMATION, APPARATUS, PRODUCT,
 
18
 * SOFTWARE, OR PROCESS DISCLOSED, OR REPRESENTS THAT ITS USE WOULD NOT
 
19
 * INFRINGE PRIVATELY OWNED RIGHTS.
 
20
 *
 
21
 * ACKNOWLEDGMENT
 
22
 *
 
23
 * This software and its documentation were produced with United States
 
24
 * Government support under Contract Number DE-AC06-76RLO-1830 awarded by
 
25
 * the United States Department of Energy.  The United States Government
 
26
 * retains a paid-up non-exclusive, irrevocable worldwide license to
 
27
 * reproduce, prepare derivative works, perform publicly and display
 
28
 * publicly by or for the US Government, including the right to
 
29
 * distribute to other US Government contractors.
 
30
 */
 
31
#ifdef USE_LUSTRE
 
32
#include <lustre/lustre_user.h> /* for O_LOV_DELAY_CREATE, LL_IOC_LOV_SETSTRIPE */
 
33
#include <linux/lustre_idl.h> /* for struct lov_mds_md, LOV_MAGIC */
 
34
#include <sys/ioctl.h> /* for ioctl */
 
35
#endif
 
36
 
 
37
#include "eliop.h"
 
38
 
 
39
#include "../sf/coms.h"
 
40
 
 
41
#if defined(CRAY) && defined(__crayx1)
 
42
#undef CRAY
 
43
#endif
 
44
 
 
45
#if  defined(AIX) || defined(DECOSF) || defined(SGITFP) || defined(SGI64) || defined(SGI_N32) || defined(CRAY) || defined(LINUXAIO)
 
46
     /* systems with Asynchronous I/O */
 
47
#else
 
48
#    ifndef NOAIO
 
49
#      define NOAIO
 
50
#    endif
 
51
#endif
 
52
 
 
53
/****************** Internal Constants and Parameters **********************/
 
54
 
 
55
#define  MAX_AIO_REQ  4
 
56
#define  NULL_AIO    -123456
 
57
#define  FOPEN_MODE 0644
 
58
#define  MAX_ATTEMPTS 10
 
59
 
 
60
 
 
61
#ifndef NOAIO
 
62
#   define AIO 1
 
63
#endif
 
64
 
 
65
 
 
66
#ifdef FFIO
 
67
#  define WRITE  ffwrite
 
68
#  define WRITEA ffwritea
 
69
#  define READ   ffread
 
70
#  define READA  ffreada
 
71
#  define CLOSE  ffclose
 
72
#  define SEEK   ffseek
 
73
#  define OPEN   ffopens
 
74
#  define DEFARG FULL
 
75
#else
 
76
#  define WRITE  write
 
77
#  define WRITEA writea
 
78
#  define READ   read
 
79
#  define READA  reada
 
80
#  define CLOSE  close
 
81
#  define SEEK   lseek
 
82
#  define OPEN   open
 
83
#  define DEFARG 0
 
84
#endif
 
85
 
 
86
 
 
87
#ifdef WIN32
 
88
#define ELIO_FSYNC _commit
 
89
#else
 
90
#include <unistd.h>
 
91
#define ELIO_FSYNC fsync
 
92
#endif
 
93
 
 
94
/* structure to emulate control block in Posix AIO */
 
95
#if defined (CRAY)
 
96
#   if defined(FFIO)
 
97
       typedef struct { struct ffsw stat; int filedes; }io_status_t;
 
98
#   else 
 
99
#      include <sys/iosw.h>
 
100
       typedef struct { struct iosw stat; int filedes; }io_status_t;
 
101
#   endif
 
102
    io_status_t cb_fout[MAX_AIO_REQ];
 
103
    io_status_t *cb_fout_arr[MAX_AIO_REQ];
 
104
 
 
105
#elif defined(AIO)
 
106
#   include <aio.h>
 
107
#   if defined(AIX)
 
108
#      define INPROGRESS EINPROG
 
109
#   else 
 
110
#      define INPROGRESS EINPROGRESS
 
111
#   endif
 
112
    struct aiocb          cb_fout[MAX_AIO_REQ];
 
113
#ifndef AIX
 
114
    const
 
115
#endif
 
116
           struct aiocb   *cb_fout_arr[MAX_AIO_REQ];
 
117
#endif
 
118
 
 
119
#ifndef INPROGRESS
 
120
#   define INPROGRESS 1
 
121
#endif
 
122
 
 
123
static long           aio_req[MAX_AIO_REQ]; /* array for AIO requests */
 
124
static int            first_elio_init = 1;  /* intialization status */
 
125
int                   _elio_Errors_Fatal=0; /* sets mode of handling errors */
 
126
 
 
127
 
 
128
/****************************** Internal Macros *****************************/
 
129
#if defined(AIO)
 
130
#  define AIO_LOOKUP(aio_i) {\
 
131
      aio_i = 0;\
 
132
      while(aio_req[aio_i] != NULL_AIO && aio_i < MAX_AIO_REQ) aio_i++;\
 
133
}
 
134
#else
 
135
#  define AIO_LOOKUP(aio_i) aio_i = MAX_AIO_REQ
 
136
#endif
 
137
 
 
138
#define SYNC_EMULATE(op) *req_id = ELIO_DONE; \
 
139
  if((stat= elio_ ## op (fd, offset, buf, bytes)) != bytes ){ \
 
140
       ELIO_ERROR(stat,0);  \
 
141
  }else \
 
142
       stat    = 0; 
 
143
 
 
144
#ifndef MIN 
 
145
#define PARIO_MIN(a,b) (((a) <= (b)) ? (a) : (b))
 
146
#endif
 
147
 
 
148
/* 
 
149
 * Offsets bigger than ABSURDLY_LARGE generate a SEEKFAIL.
 
150
 * The maximum no. of extents permitted for a file is MAX_EXTENT.
 
151
 */
 
152
 
 
153
#if defined(_LARGE_FILES) || defined(_LARGEFILE_SOURCE) || defined(_LARGEFILE64_SOURCE) || _FILE_OFFSET_BITS+0 == 64 || SIZEOF_VOIDP == 8
 
154
#   define LARGE_FILES
 
155
#endif
 
156
 
 
157
#define MAX_EXTENT 127
 
158
#ifdef LARGE_FILES
 
159
#define ABSURDLY_LARGE 1e14
 
160
#else
 
161
#define ABSURDLY_LARGE (MAX_EXTENT*2147483648.0)
 
162
#endif
 
163
 
 
164
/*****************************************************************************/
 
165
 
 
166
static Off_t elio_max_file_size(Fd_t fd)
 
167
     /* 
 
168
      * Return the maximum size permitted for this PHYSICAL file.
 
169
      * Presently not file dependent.
 
170
      */
 
171
{
 
172
#ifdef LARGE_FILES
 
173
  return ABSURDLY_LARGE;
 
174
#else
 
175
  return (2047.0*1024.0*1024.0);        /* 2 GB - 1 MB */  
 
176
#endif
 
177
}
 
178
 
 
179
static Fd_t elio_get_next_extent(Fd_t fd)
 
180
     /*
 
181
      * Return a pointer to the file descriptor that forms
 
182
      * the next extent of this file.  If the extension file
 
183
      * does not exist then it is opened.  If the open fails
 
184
      * then the usual error condition of elio_open is returned.
 
185
      */
 
186
{
 
187
  Fd_t next_fd = (Fd_t) fd->next;
 
188
  if (!next_fd) {
 
189
    /* Eventually need to replace this with user controllable naming 
 
190
     * and combine with similar logic in delete routine.
 
191
     */
 
192
    char fname[ELIO_FILENAME_MAX];
 
193
    int len;
 
194
    if (fd->extent >= MAX_EXTENT)
 
195
      return 0;
 
196
    strcpy(fname, fd->name);
 
197
    len = strlen(fname);
 
198
    if (fd->extent) len -= 4;
 
199
    sprintf(fname+len,"x%3.3d",fd->extent+1);
 
200
    /*printf("Opening extent %d with name '%s'\n",fd->extent+1,fname);*/
 
201
    if ((next_fd = elio_open(fname, fd->type, fd->mode))) {
 
202
      next_fd->extent = fd->extent + 1;
 
203
      fd->next = (struct fd_struct *) next_fd;
 
204
    }
 
205
  }
 
206
  return next_fd;
 
207
}
 
208
 
 
209
void elio_errors_fatal(int onoff)
 
210
{
 
211
    _elio_Errors_Fatal = onoff;
 
212
}
 
213
 
 
214
 
 
215
/*\ Blocking Write 
 
216
 *    - returns number of bytes written or error code (<0) if failed
 
217
\*/
 
218
Size_t elio_write(Fd_t fd, Off_t  doffset, const void* buf, Size_t bytes)
 
219
{
 
220
  off_t offset;
 
221
  Size_t stat, bytes_to_write = bytes;
 
222
  Size_t nextbytes;
 
223
 
 
224
  if (doffset >= ABSURDLY_LARGE) 
 
225
    ELIO_ERROR(SEEKFAIL,0);
 
226
 
 
227
  /* Follow the linked list of extents down until we hit the file
 
228
     that contains the offset */
 
229
  if (doffset >= elio_max_file_size(fd)) {
 
230
    Fd_t next_fd = elio_get_next_extent(fd);
 
231
    if (!next_fd) ELIO_ERROR(OPENFAIL,0);
 
232
    doffset -= elio_max_file_size(fd);
 
233
    return elio_write(next_fd, doffset, buf, bytes);
 
234
  }
 
235
 
 
236
  /* Figure out if the write continues onto the next extent */
 
237
  offset = (off_t) doffset;
 
238
  nextbytes = 0;
 
239
  if ((doffset+bytes_to_write) >= elio_max_file_size(fd)) {
 
240
    nextbytes = bytes_to_write;
 
241
    bytes_to_write = (Size_t) (elio_max_file_size(fd)-doffset);
 
242
    nextbytes -= bytes_to_write;
 
243
  }
 
244
  /*printf("TRYING TO WRITE AT doffset=%f offset=%lu bw=%lu nb=%lu\n", doffset, offset,
 
245
    bytes_to_write, nextbytes);*/
 
246
 
 
247
  /* Write to this extent */
 
248
 
 
249
#ifdef PABLO
 
250
  int pablo_code = PABLO_elio_write;
 
251
  PABLO_start( pablo_code );
 
252
#endif
 
253
  
 
254
  if(offset != SEEK(fd->fd,offset,SEEK_SET)) ELIO_ERROR(SEEKFAIL,0);
 
255
  
 
256
  while (bytes_to_write) {
 
257
    stat = WRITE(fd->fd, buf, bytes_to_write);
 
258
    if ((stat == -1) && ((errno == EINTR) || (errno == EAGAIN))) {
 
259
      ; /* interrupted write should be restarted */
 
260
    } else if (stat > 0) {
 
261
      bytes_to_write -= stat;
 
262
      buf = stat + (char*)buf; /*advance pointer by # bytes written*/
 
263
    } else {
 
264
      ELIO_ERROR(WRITFAIL, stat);
 
265
    }
 
266
  }
 
267
 
 
268
  /* Only get here if all has gone OK */
 
269
  
 
270
#ifdef PABLO
 
271
  PABLO_end(pablo_code);
 
272
#endif
 
273
 
 
274
  /* Write to next extent(s) ... relies on incrementing of buf */
 
275
  if (nextbytes) {
 
276
    Fd_t next_fd = elio_get_next_extent(fd);
 
277
    if (!next_fd) ELIO_ERROR(OPENFAIL,0);
 
278
    stat = elio_write(next_fd, (Off_t) 0, buf, nextbytes);
 
279
    if (stat != nextbytes)
 
280
      ELIO_ERROR(WRITFAIL, stat);
 
281
  }
 
282
  
 
283
  return bytes;
 
284
}
 
285
 
 
286
int elio_set_cb(Fd_t fd, Off_t doffset, int reqn, void *buf, Size_t bytes)
 
287
{
 
288
#if defined(AIO)
 
289
    off_t offset = (off_t) doffset;
 
290
#   if defined(CRAY)
 
291
       if(offset != SEEK(fd->fd, offset, SEEK_SET))return (SEEKFAIL);
 
292
       cb_fout_arr[reqn] = cb_fout+reqn;
 
293
       cb_fout[reqn].filedes    = fd->fd;
 
294
#   else
 
295
       cb_fout[reqn].aio_offset = offset;
 
296
       cb_fout_arr[reqn] = cb_fout+reqn;
 
297
         cb_fout[reqn].aio_buf    = buf;
 
298
         cb_fout[reqn].aio_nbytes = bytes;
 
299
#        if defined(AIX)
 
300
           cb_fout[reqn].aio_whence = SEEK_SET;
 
301
#        else
 
302
           cb_fout[reqn].aio_sigevent.sigev_notify = SIGEV_NONE;
 
303
           cb_fout[reqn].aio_fildes    = fd->fd;
 
304
#        endif
 
305
#   endif
 
306
#endif
 
307
    return ELIO_OK;
 
308
}
 
309
 
 
310
 
 
311
/*\ Asynchronous Write: returns 0 if succeded or err code if failed
 
312
\*/
 
313
int elio_awrite(Fd_t fd, Off_t doffset, const void* buf, Size_t bytes, io_request_t * req_id)
 
314
{
 
315
  off_t offset;
 
316
  Size_t stat;
 
317
#ifdef AIO
 
318
  int    aio_i;
 
319
#endif
 
320
 
 
321
  if (doffset >= ABSURDLY_LARGE) 
 
322
    ELIO_ERROR(SEEKFAIL,0);
 
323
 
 
324
  /* Follow the linked list of extents down until we hit the file
 
325
     that contains the offset */
 
326
  if (doffset >= elio_max_file_size(fd)) {
 
327
    Fd_t next_fd = elio_get_next_extent(fd);
 
328
    if (!next_fd) ELIO_ERROR(OPENFAIL,0);
 
329
    doffset -= elio_max_file_size(fd);
 
330
    return elio_awrite(next_fd, doffset, buf, bytes, req_id);
 
331
  }
 
332
 
 
333
  /* Figure out if the write continues onto the next extent 
 
334
   * ... if so then force the entire request to be done synchronously
 
335
   * so that we don't have to manage multiple async requests */
 
336
 
 
337
  if ((doffset+((Off_t) bytes)) >= elio_max_file_size(fd)) {
 
338
    *req_id = ELIO_DONE;
 
339
    if (elio_write(fd, doffset, buf, bytes) != bytes)
 
340
      return -1;
 
341
    else
 
342
      return 0;
 
343
  }
 
344
 
 
345
  offset = (off_t) doffset;
 
346
 
 
347
#ifdef PABLO
 
348
  int pablo_code = PABLO_elio_awrite;
 
349
  PABLO_start( pablo_code );
 
350
#endif
 
351
 
 
352
  *req_id = ELIO_DONE;
 
353
 
 
354
#ifdef AIO
 
355
   AIO_LOOKUP(aio_i);
 
356
 
 
357
   /* blocking io when request table is full */
 
358
   if(aio_i >= MAX_AIO_REQ){
 
359
#     if defined(DEBUG) && defined(ASYNC)
 
360
         fprintf(stderr, "elio_awrite: Warning- asynch overflow\n");
 
361
#     endif
 
362
      SYNC_EMULATE(write);
 
363
   } else {
 
364
      int rc;
 
365
      *req_id = (io_request_t) aio_i;
 
366
      if((rc=elio_set_cb(fd, offset, aio_i, (void*) buf, bytes)))
 
367
                                                 ELIO_ERROR(rc,0);
 
368
 
 
369
#    if defined(CRAY)
 
370
       rc = WRITEA(fd->fd, (char*)buf, bytes, &cb_fout[aio_i].stat, DEFARG);
 
371
       stat = (rc < 0)? -1 : 0; 
 
372
#    elif defined(AIX) 
 
373
#       if !defined(AIX52) && !defined(_AIO_AIX_SOURCE)
 
374
       stat = aio_write(fd->fd, cb_fout + aio_i);
 
375
#       endif
 
376
#    else
 
377
       stat = aio_write(cb_fout+aio_i);
 
378
#    endif
 
379
     aio_req[aio_i] = *req_id;
 
380
  }
 
381
 
 
382
#else
 
383
      /* call blocking write when AIO not available */
 
384
      SYNC_EMULATE(write);
 
385
#endif
 
386
 
 
387
  if(stat ==-1) ELIO_ERROR(AWRITFAIL, 0);
 
388
 
 
389
#ifdef PABLO
 
390
  PABLO_end(pablo_code);
 
391
#endif
 
392
 
 
393
  return((int)stat);
 
394
}
 
395
 
 
396
 
 
397
/*\ Truncate the file at the specified length.
 
398
\*/
 
399
int elio_truncate(Fd_t fd, Off_t dlength)
 
400
{
 
401
  off_t length = (off_t) dlength;
 
402
#ifdef WIN32
 
403
#   define ftruncate _chsize 
 
404
#endif
 
405
 
 
406
#ifdef PABLO
 
407
    int pablo_code = PABLO_elio_truncate;
 
408
    PABLO_start( pablo_code );
 
409
#endif
 
410
    if(dlength >= elio_max_file_size(fd)){
 
411
      Fd_t next_fd = elio_get_next_extent(fd);
 
412
      dlength -= elio_max_file_size(fd);
 
413
#       if defined(DEBUG)
 
414
      printf(stderr," calling ftruncate with length = %f \n", dlength);
 
415
#endif
 
416
      return elio_truncate(next_fd, dlength);
 
417
    }
 
418
    (void) SEEK(fd->fd, 0L, SEEK_SET);
 
419
    if (ftruncate(fd->fd, length))
 
420
    return TRUNFAIL;
 
421
    else {
 
422
    return ELIO_OK;
 
423
    }
 
424
#ifdef PABLO
 
425
    PABLO_end(pablo_code);
 
426
#endif
 
427
}
 
428
 
 
429
 
 
430
/*\ Return in length the length of the file
 
431
\*/
 
432
int elio_length(Fd_t fd, Off_t *dlength)
 
433
{
 
434
  off_t length;
 
435
  int status;
 
436
 
 
437
  /* Add up the lengths of any extents */
 
438
  if (fd->next) {
 
439
    status = elio_length((Fd_t) fd->next, dlength);
 
440
    *dlength += elio_max_file_size(fd);
 
441
    return status;
 
442
  }
 
443
  else {
 
444
#ifdef PABLO
 
445
    int pablo_code = PABLO_elio_length;
 
446
    PABLO_start( pablo_code );
 
447
#endif
 
448
    
 
449
    if ((length = SEEK(fd->fd, (off_t) 0, SEEK_END)) != -1)
 
450
      status = ELIO_OK;
 
451
    else
 
452
      status = SEEKFAIL;
 
453
    
 
454
#ifdef PABLO
 
455
    PABLO_end(pablo_code);
 
456
#endif
 
457
    
 
458
    *dlength = (Off_t) length;
 
459
    return status;
 
460
  }
 
461
}
 
462
 
 
463
 
 
464
/*\ Blocking Read 
 
465
 *      - returns number of bytes read or error code (<0) if failed
 
466
\*/
 
467
Size_t elio_read(Fd_t fd, Off_t doffset, void* buf, Size_t bytes)
 
468
{
 
469
off_t offset;
 
470
Size_t stat, bytes_to_read = bytes;
 
471
Size_t nextbytes;
 
472
int    attempt=0;
 
473
 
 
474
 if (doffset >= ABSURDLY_LARGE) 
 
475
    ELIO_ERROR(SEEKFAIL,0);
 
476
 
 
477
  /* Follow the linked list of extents down until we hit the file
 
478
     that contains the offset */
 
479
  if (doffset >= elio_max_file_size(fd)) {
 
480
    Fd_t next_fd = elio_get_next_extent(fd);
 
481
    if (!next_fd) ELIO_ERROR(OPENFAIL,0);
 
482
    doffset -= elio_max_file_size(fd);
 
483
    return elio_read(next_fd, doffset, buf, bytes);
 
484
  }
 
485
 
 
486
  /* Figure out if the read continues onto the next extent */
 
487
  offset = (off_t) doffset;
 
488
  nextbytes = 0;
 
489
  if ((doffset+bytes_to_read) >= elio_max_file_size(fd)) {
 
490
    nextbytes = bytes_to_read;
 
491
    bytes_to_read = (Size_t) (elio_max_file_size(fd)-doffset);
 
492
    nextbytes -= bytes_to_read;
 
493
  }
 
494
 
 
495
 
 
496
  /* Read from this physical file */
 
497
 
 
498
#ifdef PABLO
 
499
  int pablo_code = PABLO_elio_read;
 
500
  PABLO_start( pablo_code );
 
501
#endif
 
502
 
 
503
  if(offset != SEEK(fd->fd,offset,SEEK_SET)) ELIO_ERROR(SEEKFAIL,0);
 
504
  
 
505
  while (bytes_to_read) {
 
506
    stat = READ(fd->fd, buf, bytes_to_read);
 
507
    if(stat==0){
 
508
      ELIO_ERROR(EOFFAIL, stat);
 
509
    } else if ((stat == -1) && ((errno == EINTR) || (errno == EAGAIN))) {
 
510
      ; /* interrupted read should be restarted */
 
511
    } else if (stat > 0) {
 
512
      bytes_to_read -= stat;
 
513
      buf = stat + (char*)buf; /*advance pointer by # bytes read*/
 
514
    } else {
 
515
      ELIO_ERROR(READFAIL, stat);
 
516
    }
 
517
    attempt++;
 
518
  }
 
519
  
 
520
  /* Only get here if all went OK */
 
521
  
 
522
#ifdef PABLO
 
523
  PABLO_end(pablo_code);
 
524
#endif
 
525
  
 
526
  /* Read from next extent(s) ... relies on incrementing of buf */
 
527
  if (nextbytes) {
 
528
    Fd_t next_fd = elio_get_next_extent(fd);
 
529
    if (!next_fd) ELIO_ERROR(OPENFAIL,0);
 
530
    stat = elio_read(next_fd, (Off_t) 0, buf, nextbytes);
 
531
    if (stat != nextbytes)
 
532
      ELIO_ERROR(READFAIL, stat);
 
533
  }
 
534
 
 
535
 
 
536
  return bytes;
 
537
}
 
538
 
 
539
 
 
540
 
 
541
/*\ Asynchronous Read: returns 0 if succeded or -1 if failed
 
542
\*/
 
543
int elio_aread(Fd_t fd, Off_t doffset, void* buf, Size_t bytes, io_request_t * req_id)
 
544
{
 
545
  off_t offset = (off_t) doffset;
 
546
  Size_t stat;
 
547
#ifdef AIO
 
548
  int    aio_i;
 
549
#endif
 
550
#ifdef CRAY
 
551
  int rc;
 
552
#endif
 
553
 
 
554
  if (doffset >= ABSURDLY_LARGE) 
 
555
    ELIO_ERROR(SEEKFAIL,0);
 
556
 
 
557
  /* Follow the linked list of extents down until we hit the file
 
558
     that contains the offset */
 
559
  if (doffset >= elio_max_file_size(fd)) {
 
560
    Fd_t next_fd = elio_get_next_extent(fd);
 
561
    if (!next_fd) ELIO_ERROR(OPENFAIL,0);
 
562
    doffset -= elio_max_file_size(fd);
 
563
    return elio_aread(next_fd, doffset, buf, bytes, req_id);
 
564
  }
 
565
 
 
566
  /* Figure out if the read continues onto the next extent 
 
567
   * ... if so then force the entire request to be done synchronously
 
568
   * so that we don't have to manage multiple async requests */
 
569
 
 
570
  if ((doffset+((Off_t) bytes)) >= elio_max_file_size(fd)) {
 
571
    *req_id = ELIO_DONE;
 
572
    if (elio_read(fd, doffset, buf, bytes) != bytes)
 
573
      return -1;
 
574
    else
 
575
      return 0;
 
576
  }
 
577
 
 
578
  offset = (off_t) doffset;
 
579
 
 
580
#ifdef PABLO
 
581
  int pablo_code = PABLO_elio_aread;
 
582
  PABLO_start( pablo_code );
 
583
#endif
 
584
 
 
585
  *req_id = ELIO_DONE;
 
586
 
 
587
#ifdef AIO
 
588
    AIO_LOOKUP(aio_i);
 
589
 
 
590
    /* blocking io when request table is full */
 
591
    if(aio_i >= MAX_AIO_REQ){
 
592
#       if defined(DEBUG)
 
593
           fprintf(stderr, "elio_read: Warning- asynch overflow\n");
 
594
#       endif
 
595
        SYNC_EMULATE(read);
 
596
 
 
597
    } else {
 
598
 
 
599
       *req_id = (io_request_t) aio_i;
 
600
        if((stat=elio_set_cb(fd, offset, aio_i, (void*) buf, bytes)))
 
601
                                                 ELIO_ERROR((int)stat,0);
 
602
#       if defined(CRAY)
 
603
          rc = READA(fd->fd, buf, bytes, &cb_fout[aio_i].stat, DEFARG);
 
604
          stat = (rc < 0)? -1 : 0;
 
605
#       elif defined(AIX)
 
606
#if    !defined(AIX52) && !defined(_AIO_AIX_SOURCE)
 
607
          stat = aio_read(fd->fd, cb_fout+aio_i);
 
608
#endif
 
609
#       else
 
610
          stat = aio_read(cb_fout+aio_i);
 
611
#       endif
 
612
        aio_req[aio_i] = *req_id;
 
613
    }
 
614
#else
 
615
 
 
616
    /* call blocking write when AIO not available */
 
617
    SYNC_EMULATE(read);
 
618
 
 
619
#endif
 
620
 
 
621
    if(stat ==-1) ELIO_ERROR(AWRITFAIL, 0);
 
622
 
 
623
#ifdef PABLO
 
624
    PABLO_end(pablo_code);
 
625
#endif
 
626
 
 
627
    return((int)stat);
 
628
}
 
629
 
 
630
 
 
631
/*\ Wait for asynchronous I/O operation to complete. Invalidate id.
 
632
\*/
 
633
int elio_wait(io_request_t *req_id)
 
634
{
 
635
  int  aio_i=0;
 
636
  int  rc;
 
637
 
 
638
  rc=0; /* just to remove the compiler warning */
 
639
#ifdef PABLO
 
640
  int pablo_code = PABLO_elio_wait;
 
641
  PABLO_start( pablo_code );
 
642
#endif
 
643
 
 
644
  if(*req_id != ELIO_DONE ) { 
 
645
 
 
646
#    ifdef AIO
 
647
#      if defined(CRAY)
 
648
 
 
649
#        if defined(FFIO)
 
650
         {
 
651
            struct ffsw dumstat, *prdstat=&(cb_fout[*req_id].stat);
 
652
            fffcntl(cb_fout[*req_id].filedes, FC_RECALL, prdstat, &dumstat);
 
653
            if (FFSTAT(*prdstat) == FFERR) ELIO_ERROR(SUSPFAIL,0);
 
654
         }
 
655
#        else
 
656
         {
 
657
            struct iosw *statlist[1];
 
658
            statlist[0] = &(cb_fout[*req_id].stat);
 
659
            recall(cb_fout[*req_id].filedes, 1, statlist); 
 
660
         }
 
661
#        endif
 
662
 
 
663
#      elif defined(AIX) 
 
664
#         if    !defined(AIX52) && !defined(_AIO_AIX_SOURCE)
 
665
              do {    /* I/O can be interrupted on SP through rcvncall ! */
 
666
                   rc =(int)aio_suspend(1, cb_fout_arr+(int)*req_id);
 
667
              } while(rc == -1 && errno == EINTR); 
 
668
#         endif
 
669
 
 
670
#  else
 
671
      if((int)aio_suspend((const struct aiocb *const*)(cb_fout_arr+(int)*req_id), 1, NULL) != 0) rc =-1;
 
672
#  endif
 
673
      if(rc ==-1) ELIO_ERROR(SUSPFAIL,0);
 
674
 
 
675
#  if defined(DECOSF)
 
676
      /* on DEC aio_return is required to clean internal data structures */
 
677
      if(aio_return(cb_fout+(int)*req_id) == -1) ELIO_ERROR(RETUFAIL,0);
 
678
#  endif
 
679
#endif
 
680
 
 
681
      while(aio_req[aio_i] != *req_id && aio_i < MAX_AIO_REQ) aio_i++;
 
682
      if(aio_i >= MAX_AIO_REQ) ELIO_ERROR(HANDFAIL, aio_i);
 
683
 
 
684
      aio_req[aio_i] = NULL_AIO;
 
685
      *req_id = ELIO_DONE;
 
686
   }
 
687
 
 
688
#ifdef PABLO
 
689
   PABLO_end(pablo_code);
 
690
#endif
 
691
 
 
692
   return ELIO_OK;
 
693
}
 
694
 
 
695
 
 
696
 
 
697
/*\ Check if asynchronous I/O operation completed. If yes, invalidate id.
 
698
\*/
 
699
int elio_probe(io_request_t *req_id, int* status)
 
700
{
 
701
  int    errval=-1;
 
702
  int    aio_i = 0;
 
703
     
 
704
#ifdef PABLO
 
705
  int pablo_code = PABLO_elio_probe;
 
706
  PABLO_start( pablo_code );
 
707
#endif
 
708
 
 
709
  if(*req_id == ELIO_DONE){
 
710
      *status = ELIO_DONE;
 
711
  } else {
 
712
      
 
713
#ifdef AIO
 
714
#    if defined(CRAY)
 
715
 
 
716
#     if defined(FFIO)
 
717
      {
 
718
         struct ffsw dumstat, *prdstat=&(cb_fout[*req_id].stat);
 
719
         fffcntl(cb_fout[*req_id].filedes, FC_ASPOLL, prdstat, &dumstat);
 
720
         errval = (FFSTAT(*prdstat) == 0) ? INPROGRESS: 0;
 
721
      }
 
722
#     else
 
723
 
 
724
         errval = ( IO_DONE(cb_fout[*req_id].stat) == 0)? INPROGRESS: 0;
 
725
 
 
726
#     endif
 
727
 
 
728
#   elif defined(AIX)
 
729
      errval = aio_error(cb_fout[(int)*req_id].aio_handle);
 
730
#   else
 
731
      errval = aio_error(cb_fout+(int)*req_id);
 
732
#   endif
 
733
#endif
 
734
      switch (errval) {
 
735
      case 0: 
 
736
          while(aio_req[aio_i] != *req_id && aio_i < MAX_AIO_REQ) aio_i++;
 
737
          if(aio_i >= MAX_AIO_REQ) ELIO_ERROR(HANDFAIL, aio_i);
 
738
 
 
739
      *req_id = ELIO_DONE; 
 
740
      *status = ELIO_DONE;
 
741
      aio_req[aio_i] = NULL_AIO;
 
742
      break;
 
743
      case INPROGRESS:
 
744
      *status = ELIO_PENDING; 
 
745
      break;
 
746
      default:
 
747
          return PROBFAIL;
 
748
      }
 
749
  }
 
750
 
 
751
#ifdef PABLO
 
752
  PABLO_end(pablo_code);
 
753
#endif
 
754
 
 
755
  return ELIO_OK;
 
756
}
 
757
 
 
758
 
 
759
#if defined(CRAY) && defined(FFIO)
 
760
static int cray_part_info(char *dirname,long *pparts,long *sparts)
 
761
{
 
762
  struct statfs stats;
 
763
  long temp,count=0;
 
764
 
 
765
  if(statfs(dirname, &stats, sizeof(struct statfs), 0) == -1) return -1;
 
766
 
 
767
  temp = stats.f_priparts;
 
768
  while(temp != 0){
 
769
      count++;
 
770
      temp <<= 1;
 
771
  }
 
772
 *pparts = count;
 
773
 
 
774
 if(stats.f_secparts != 0){
 
775
 
 
776
    temp = (stats.f_secparts << count);
 
777
    count = 0;
 
778
    while(temp != 0){
 
779
           count++;
 
780
           temp <<= 1;
 
781
    }
 
782
    *sparts = count;
 
783
 }
 
784
 return ELIO_OK;
 
785
 
 
786
}
 
787
 
 
788
#endif
 
789
 
 
790
 
 
791
/*\ Noncollective File Open
 
792
\*/
 
793
Fd_t  elio_open(const char* fname, int type, int mode)
 
794
{
 
795
  Fd_t fd=NULL;
 
796
  stat_t statinfo;
 
797
  int ptype=0, rc;
 
798
  char dirname[ELIO_FILENAME_MAX];
 
799
 
 
800
  /*
 
801
    Create a file for writing to in lustre with
 
802
    a specified pagesize and stripe.
 
803
    pagesize = 1048576;
 
804
    lustre_stripe_count = 32;
 
805
    are good choices.
 
806
  */
 
807
#ifdef USE_LUSTRE
 
808
  struct lov_mds_md stripecfg;
 
809
  int    lustre_file;
 
810
  int  lustre_stripe_count;
 
811
  int  pagesize;
 
812
  pagesize = 1048576;
 
813
  lustre_stripe_count = 32;
 
814
#endif
 
815
 
 
816
#ifdef PABLO
 
817
  int pablo_code = PABLO_elio_open;
 
818
  PABLO_start( pablo_code );
 
819
#endif
 
820
 
 
821
  if(first_elio_init) elio_init();
 
822
 
 
823
   switch(type){
 
824
     case ELIO_W:  ptype = O_CREAT | O_TRUNC | O_WRONLY;
 
825
                   break;
 
826
     case ELIO_R:  ptype = O_RDONLY;
 
827
                   break;
 
828
     case ELIO_RW: ptype = O_CREAT | O_RDWR;
 
829
                   break;
 
830
     default:      
 
831
                   ELIO_ERROR_NULL(MODEFAIL, type);
 
832
   }
 
833
 
 
834
#if defined(WIN32) || defined(CYGNUS)
 
835
   ptype |= O_BINARY;
 
836
#endif
 
837
 
 
838
  if((fd = (Fd_t ) malloc(sizeof(fd_struct)) ) == NULL) 
 
839
                   ELIO_ERROR_NULL(ALOCFAIL, 0);
 
840
 
 
841
  if( (rc = elio_dirname(fname, dirname, ELIO_FILENAME_MAX)) != ELIO_OK) {
 
842
                   free(fd);
 
843
                   ELIO_ERROR_NULL(rc, 0);
 
844
  }
 
845
 
 
846
  if( (rc = elio_stat(dirname, &statinfo)) != ELIO_OK) {
 
847
                   free(fd);
 
848
                   ELIO_ERROR_NULL(rc, 0);
 
849
  }
 
850
 
 
851
  fd->fs = statinfo.fs;
 
852
  fd->mode = mode;
 
853
  fd->type = type;
 
854
  fd->extent = 0;
 
855
  fd->next = NULL;
 
856
  
 
857
#ifdef USE_LUSTRE
 
858
  lustre_file = (strncmp(fname,"/dtemp",6) == 0) && (access(fname, F_OK) != 0) && (ME() == 0);
 
859
  if (lustre_file) {
 
860
    ptype = ptype | O_LOV_DELAY_CREATE ;
 
861
  }
 
862
#endif
 
863
 
 
864
#if defined(CRAY) && defined(FFIO)
 
865
  {
 
866
    struct ffsw ffstat;
 
867
    long pparts, sparts, cbits, cblocks;
 
868
    extern long _MPP_MY_PE;
 
869
    char *ffio_str="cache:256"; /*  intern I/O buffer/cache 256*4096 bytes */ 
 
870
                                /*  JN: we do not want read-ahead write-behind*/
 
871
 
 
872
    if(cray_part_info(dirname,&pparts,&sparts) != ELIO_OK){
 
873
                   free(fd);
 
874
                   ELIO_ERROR_NULL(STATFAIL, 0);
 
875
    }
 
876
 
 
877
    ptype |= ( O_BIG | O_PLACE | O_RAW );
 
878
    cbits = (sparts != 0) ? 1 : 0;
 
879
 
 
880
    if( sparts != 0) {
 
881
 
 
882
      /* stripe is set so we only select secondary partitions with cbits */
 
883
      if(mode == ELIO_SHARED){
 
884
         cbits = ~((~0L)<<PARIO_MIN(32,sparts)); /* use all secondary partitions */
 
885
         cblocks = 100;
 
886
      }else{
 
887
         cbits = 1 << (_MPP_MY_PE%sparts);  /* round robin over s part */
 
888
      }
 
889
 
 
890
      cbits <<= pparts;        /* move us out of the primary partitions */
 
891
 
 
892
     }
 
893
 
 
894
     
 
895
/*     printf ("parts=%d cbits = %X\n",sparts,cbits);*/
 
896
 
 
897
     if(mode == ELIO_SHARED)
 
898
      fd->fd = OPEN(fname, ptype, FOPEN_MODE, cbits, cblocks, &ffstat, NULL);
 
899
     else
 
900
      fd->fd = OPEN(fname, ptype, FOPEN_MODE, 0L   , 0      , &ffstat, ffio_str);
 
901
 
 
902
  }
 
903
#else
 
904
  fd->fd = OPEN(fname, ptype, FOPEN_MODE );
 
905
#endif
 
906
 
 
907
  if( (int)fd->fd == -1) {
 
908
                   free(fd);
 
909
                   ELIO_ERROR_NULL(OPENFAIL, 0);
 
910
  }
 
911
  
 
912
  fd->name = strdup(fname);
 
913
 
 
914
#ifdef USE_LUSTRE
 
915
    if (lustre_file) {
 
916
      stripecfg.lmm_magic = LOV_MAGIC;
 
917
      stripecfg.lmm_pattern = 0; /* Only available option for now. */
 
918
      stripecfg.lmm_stripe_size = pagesize; /* Stripe size in bytes. */
 
919
      stripecfg.lmm_stripe_count  = lustre_stripe_count;
 
920
      if (ioctl((int)fd->fd, LL_IOC_LOV_SETSTRIPE, &stripecfg) < 0) {
 
921
        fprintf(stderr,
 
922
              "fp_create_out_filefp: Error: unable to stripe %s file.\n"
 
923
              "error was %s\n",
 
924
              fname,strerror(errno));
 
925
        fflush(stderr);
 
926
        free(fd);
 
927
        ELIO_ERROR_NULL(OPENFAIL, 0);
 
928
      }
 
929
    } /* end if (luster_file) (is in /dtemp) */
 
930
#endif
 
931
 
 
932
#ifdef PABLO
 
933
  PABLO_end(pablo_code);
 
934
#endif
 
935
 
 
936
  return(fd);
 
937
}
 
938
 
 
939
/*\ Close File
 
940
\*/
 
941
int elio_close(Fd_t fd)
 
942
{
 
943
    int status = ELIO_OK;
 
944
#ifdef PABLO
 
945
    pablo_code = PABLO_elio_close;
 
946
    PABLO_start( pablo_code );
 
947
#endif
 
948
 
 
949
    if (fd->next)
 
950
      status = elio_close((Fd_t) fd->next);
 
951
 
 
952
    /*printf("Closing extent %d name %s\n", fd->extent, fd->name);*/
 
953
    if(CLOSE(fd->fd)==-1 || (status != ELIO_OK)) 
 
954
      ELIO_ERROR(CLOSFAIL, 0);
 
955
 
 
956
    free(fd->name);
 
957
    free(fd);
 
958
 
 
959
#ifdef PABLO
 
960
    PABLO_end(pablo_code);
 
961
#endif
 
962
    return ELIO_OK;
 
963
}
 
964
 
 
965
 
 
966
 
 
967
/*\ Close File
 
968
\*/
 
969
int elio_fsync(Fd_t fd)
 
970
{
 
971
    int status = ELIO_OK;
 
972
 
 
973
#ifdef ELIO_FSYNC
 
974
    if (fd->next)
 
975
      status = elio_fsync((Fd_t) fd->next);
 
976
 
 
977
    /* printf("syncing extent %d name %s\n", fd->extent, fd->name); */
 
978
    /*   if(ELIO_FSYNC(fd->fd)==-1 || (status != ELIO_OK)) */
 
979
#ifndef WIN32
 
980
#if !defined(__INTERIX) 
 
981
#ifdef CATAMOUNT
 
982
      status = fsync((Fd_t) fd->next);
 
983
#else
 
984
    sync();
 
985
#endif
 
986
#endif
 
987
#endif
 
988
    if(ELIO_FSYNC(fd->fd)==-1 )
 
989
      ELIO_ERROR(FSYNCFAIL, 0);
 
990
#endif
 
991
 
 
992
    return ELIO_OK;
 
993
}
 
994
 
 
995
 
 
996
/*\ Delete File
 
997
\*/
 
998
int elio_delete(const char* filename)
 
999
{
 
1000
    int rc;
 
1001
 
 
1002
    if (access(filename, F_OK) != 0) /* Succeed if the file does not exist */
 
1003
      return ELIO_OK;
 
1004
 
 
1005
#ifdef PABLO
 
1006
    int pablo_code = PABLO_elio_delete;
 
1007
    PABLO_start( pablo_code );
 
1008
#endif
 
1009
 
 
1010
    rc = unlink(filename);
 
1011
 
 
1012
    /* Remeber the first rc ... now delete possible extents until
 
1013
       one fails */
 
1014
 
 
1015
    {
 
1016
      int extent;
 
1017
      for (extent=1; extent<MAX_EXTENT; extent++) {
 
1018
    char fname[ELIO_FILENAME_MAX];
 
1019
    sprintf(fname,"%sx%3.3d",filename,extent);
 
1020
    /*printf("Deleting extent %d with name '%s'\n",extent,fname);*/
 
1021
    if (unlink(fname)) break;
 
1022
      }
 
1023
    }
 
1024
    
 
1025
    if(rc ==-1) ELIO_ERROR(DELFAIL,0);
 
1026
 
 
1027
#ifdef PABLO
 
1028
    PABLO_end(pablo_code);
 
1029
#endif
 
1030
    return(ELIO_OK);
 
1031
}
 
1032
 
 
1033
 
 
1034
 
 
1035
/*\ Initialize ELIO
 
1036
\*/
 
1037
void elio_init(void)
 
1038
{
 
1039
  if(first_elio_init) {
 
1040
#     if defined(ASYNC)
 
1041
           int i;
 
1042
           for(i=0; i < MAX_AIO_REQ; i++)
 
1043
         aio_req[i] = NULL_AIO;
 
1044
#     endif
 
1045
      first_elio_init = 0;
 
1046
  }
 
1047
}
 
1048
 
 
1049
 
 
1050
/*\ Return Error String Associated with Given Error Code 
 
1051
\*/
 
1052
void elio_errmsg(int code, char *msg)
 
1053
{
 
1054
     if(code==ELIO_OK){
 
1055
         (void) strcpy(msg, ">OK");
 
1056
         return;
 
1057
     }
 
1058
     else if(code == ELIO_PENDING_ERR) code = elio_pending_error;
 
1059
 
 
1060
     if(code<OFFSET || code >OFFSET+ERRLEN) *msg=(char)0;
 
1061
     else (void) strcpy(msg, errtable[-OFFSET + code]);
 
1062
}
 
1063
      
 
1064
 
 
1065
int elio_pending_error=UNKNFAIL;
 
1066
 
 
1067
char *errtable[ERRLEN] ={
 
1068
">Unable to Seek",
 
1069
">Write Failed",
 
1070
">Asynchronous Write Failed",
 
1071
">Read Failed",
 
1072
">Asynchronous Read Failed",
 
1073
">Suspend Failed",
 
1074
">I/O Request Handle not in Table",
 
1075
">Incorrect File Mode",
 
1076
">Unable to Determine Directory",
 
1077
">Stat For Specified File or Directory Failed",
 
1078
">Open Failed",
 
1079
">Unable To Allocate Internal Data Structure",
 
1080
">Unsupported Feature",
 
1081
">Unlink Failed",
 
1082
">Close Failed",
 
1083
">Operation Interrupted Too Many Times",
 
1084
">AIO Return Failed",
 
1085
">Name String too Long",
 
1086
">Unable to Determine Filesystem Type",
 
1087
">Numeric Conversion Error", 
 
1088
">Incorrect Filesystem/Device Type",
 
1089
">Error in Probe",
 
1090
">Unable to Truncate",
 
1091
">End of File",
 
1092
">Fsync Failed",
 
1093
""};