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

« back to all changes in this revision

Viewing changes to src/tools/ga-5-1/pario/eaf/eaf.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
 
 * DISCLAIMER
7
 
 *
8
 
 * This material was prepared as an account of work sponsored by an
9
 
 * agency of the United States Government.  Neither the United States
10
 
 * Government nor the United States Department of Energy, nor Battelle,
11
 
 * nor any of their employees, MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR
12
 
 * ASSUMES ANY LEGAL LIABILITY OR RESPONSIBILITY FOR THE ACCURACY,
13
 
 * COMPLETENESS, OR USEFULNESS OF ANY INFORMATION, APPARATUS, PRODUCT,
14
 
 * SOFTWARE, OR PROCESS DISCLOSED, OR REPRESENTS THAT ITS USE WOULD NOT
15
 
 * INFRINGE PRIVATELY OWNED RIGHTS.
16
 
 *
17
 
 *
18
 
 * ACKNOWLEDGMENT
19
 
 *
20
 
 * This software and its documentation were produced with United States
21
 
 * Government support under Contract Number DE-AC06-76RLO-1830 awarded by
22
 
 * the United States Department of Energy.  The United States Government
23
 
 * retains a paid-up non-exclusive, irrevocable worldwide license to
24
 
 * reproduce, prepare derivative works, perform publicly and display
25
 
 * publicly by or for the US Government, including the right to
26
 
 * distribute to other US Government contractors.
27
 
 */
28
 
#if HAVE_STDIO_H
29
 
#   include <stdio.h>
30
 
#endif
31
 
#if HAVE_STDLIB_H
32
 
#   include <stdlib.h>
33
 
#endif
34
 
#if HAVE_STRING_H
35
 
#   include <string.h>
36
 
#endif
37
 
#if HAVE_LINUX_LIMITS_H
38
 
#   include <linux/limits.h>
39
 
#endif
40
 
#if HAVE_LIMITS_H
41
 
#   include <limits.h>
42
 
#endif
43
 
 
44
 
#ifdef WIN32
45
 
#   define PATH_MAX _MAX_PATH
46
 
#   define F_OK 2
47
 
#else
48
 
#   include <unistd.h>
49
 
#endif
50
 
 
51
 
#ifdef EAF_STATS
52
 
#   include <sys/types.h>
53
 
#   include <sys/time.h>
54
 
#endif
55
 
 
56
 
#include "elio.h"
57
 
#include "eaf.h"
58
 
#include "eafP.h"
59
 
#include "macdecls.h"
60
 
 
61
 
#ifdef OPEN_MAX
62
 
#   define EAF_MAX_FILES OPEN_MAX
63
 
#else
64
 
#   define EAF_MAX_FILES 1024
65
 
#endif
66
 
 
67
 
 
68
 
static struct {
69
 
    char *fname;      /**< Filename --- if non-null is active*/
70
 
    Fd_t elio_fd;     /**< ELIO file descriptor */
71
 
    int type;         /**< file type */
72
 
    int nwait;        /**< #waits */
73
 
    int nwrite;       /**< #synchronous writes */
74
 
    int nread;        /**< #synchronous reads */
75
 
    int nawrite;      /**< #asynchronous writes */
76
 
    int naread;       /**< #asynchronous reads */
77
 
    double nb_write;  /**< #synchronous bytes written */
78
 
    double nb_read;   /**< #synchronous bytes read */
79
 
    double nb_awrite; /**< #asynchronous bytes written */
80
 
    double nb_aread;  /**< #asynchronous bytes read */
81
 
    double t_write;   /**< Wall seconds synchronous writing */
82
 
    double t_read;    /**< Wall seconds synchronous reading */
83
 
    double t_awrite;  /**< Wall seconds asynchronous writing */
84
 
    double t_aread;   /**< Wall seconds asynchronous reading */
85
 
    double t_wait;    /**< Wall seconds waiting */
86
 
    long size;        /**< size for MA hack */
87
 
    long handle;      /**< handle for MA hack */
88
 
    char *pointer;    /**< pointer for MA */
89
 
    long openma;      /**< open yes or no for MA to simulate file behavoir */
90
 
} file[EAF_MAX_FILES];
91
 
 
92
 
 
93
 
int eaf_flushbuf(int , eaf_off_t , const void *, size_t );
94
 
 
95
 
static int valid_fd(int fd)
96
 
{
97
 
    return ( (fd >= 0) && (fd < EAF_MAX_FILES) && (file[fd].fname) );
98
 
}
99
 
 
100
 
 
101
 
/**
102
 
 * Return wall_time in seconds as cheaply and as accurately as possible
103
 
 */
104
 
static double wall_time(void)
105
 
{
106
 
#ifdef EAF_STATS
107
 
    static int firstcall = 1;
108
 
    static unsigned firstsec, firstusec;
109
 
    double low, high;
110
 
    struct timeval tp;
111
 
    struct timezone tzp;
112
 
 
113
 
    if (firstcall) {
114
 
        (void) gettimeofday(&tp,&tzp);
115
 
        firstusec = tp.tv_usec;
116
 
        firstsec  = tp.tv_sec;
117
 
        firstcall = 0;
118
 
    }
119
 
 
120
 
    (void) gettimeofday(&tp,&tzp);
121
 
 
122
 
    low = (double) (tp.tv_usec>>1) - (double) (firstusec>>1);
123
 
    high = (double) (tp.tv_sec - firstsec);
124
 
 
125
 
    return high + 1.0e-6*(low+low);
126
 
#else /* EAF_STATS */
127
 
    return 0.0;
128
 
#endif /* EAF_STATS */
129
 
}
130
 
 
131
 
 
132
 
/**
133
 
 * Open the named file returning the EAF file descriptor in fd.
134
 
 * Return 0 on success, non-zero on failure
135
 
 */
136
 
int EAF_Open(const char *fname, int type, int *fd)
137
 
{
138
 
  int i=0, j=0, found=0;
139
 
  char *ptr;
140
 
  long handle, index;
141
 
#ifdef CRAY_XT
142
 
    int myid;
143
 
#   include <mpi.h>
144
 
#endif
145
 
    while ((i<EAF_MAX_FILES) && file[i].fname) /* Find first empty slot */
146
 
        i++;
147
 
    if (i == EAF_MAX_FILES) return EAF_ERR_MAX_OPEN;
148
 
        
149
 
    file[i].size=0;
150
 
    for (j=0; j< i; j++){
151
 
      if(strcmp(file[j].fname,fname) == 0 && file[j].size >0) {
152
 
        found=1;
153
 
        break;
154
 
      }
155
 
    }
156
 
      
157
 
    if(type > 0) {
158
 
      /* check if this file aka MA region labeled by fname is already open with size >=0*/
159
 
#ifdef DEBUG
160
 
      printf(" JJJ %d III %d fname %s filejfname %s found %d \n", j, i, fname, file[j].fname, found);
161
 
#endif
162
 
      if(found == 0 ) {
163
 
/* if arg gt 1M then use remainder as size */
164
 
        /* we grab 3/4 of avail mem */
165
 
        if(type > 1000000) {
166
 
          file[i].size=type-1000000;
167
 
        }else{
168
 
        file[i].size=MA_inquire_avail(MT_CHAR)*8/10;
169
 
        }
170
 
 
171
 
        if (!MA_alloc_get(MT_CHAR, file[i].size, fname, &handle, &index))
172
 
          return EAF_ERR_OPEN;
173
 
    /* MA hack: we pass   type = sizeof MA alloc in megabytes */
174
 
        MA_get_pointer(handle, &ptr);
175
 
    if (!(file[i].fname = strdup(fname)))
176
 
        return EAF_ERR_MEMORY;
177
 
      file[i].pointer=ptr;
178
 
      file[i].handle=handle;
179
 
      file[i].openma=1;
180
 
      }else{
181
 
#ifdef DEBUG
182
 
          printf(" found old fileMA  %d size %ld \n", j, file[j].size);
183
 
#endif
184
 
          /* need check if new size is <= old size*/
185
 
          i=j;
186
 
          
187
 
      file[i].openma=1;
188
 
      }
189
 
        type=0;
190
 
#ifdef DEBUG
191
 
      printf(" size %ld ptr %p \n", file[i].size, file[i].pointer);
192
 
#endif
193
 
      }else{
194
 
    if (!(file[i].fname = strdup(fname)))
195
 
        return EAF_ERR_MEMORY;
196
 
 
197
 
      if(type > 0) type = EAF_RW;
198
 
#ifdef DEBUG
199
 
      printf(" opening regular %d eaf %s \n", i, fname);
200
 
#endif
201
 
 
202
 
      if (!(file[i].elio_fd = elio_open(fname, type, ELIO_PRIVATE))) {
203
 
#ifdef CRAY_XT
204
 
        MPI_Comm_rank(MPI_COMM_WORLD,&myid);
205
 
        /* printf(" %d sleeping for %d usec \n", myid, (myid+1)/4); */
206
 
        usleep((myid+1)/4);
207
 
        if (!(file[i].elio_fd = elio_open(fname, type, ELIO_PRIVATE))) {
208
 
#endif
209
 
            free(file[i].fname);
210
 
            file[i].fname = 0;
211
 
            return ELIO_PENDING_ERR;
212
 
#ifdef CRAY_XT
213
 
        }
214
 
#endif
215
 
      }
216
 
    }
217
 
 
218
 
    file[i].nwait = file[i].nread = file[i].nwrite = 
219
 
        file[i].naread = file[i].nawrite = 0;
220
 
    file[i].nb_read = file[i].nb_write = file[i].nb_aread = 
221
 
        file[i].nb_awrite = file[i].t_read = file[i].t_write = 
222
 
        file[i].t_wait = 0.0;
223
 
 
224
 
    file[i].type = type;
225
 
    *fd = i;
226
 
    return EAF_OK;
227
 
}
228
 
 
229
 
 
230
 
/**
231
 
 * Close the EAF file and return 0 on success, non-zero on failure
232
 
 */
233
 
int EAF_Close(int fd)
234
 
{
235
 
    if (!valid_fd(fd)) return EAF_ERR_INVALID_FD;
236
 
    
237
 
    if (file[fd].size > 0) {
238
 
#ifdef DEBUG
239
 
      printf(" maclosing %d %s \n", fd, file[fd].fname);
240
 
#endif
241
 
      file[fd].openma=0;
242
 
      return 0;
243
 
    }else{
244
 
#ifdef DEBUG
245
 
      printf(" closing regular file %s fd %d \n", file[fd].fname, fd);
246
 
#endif
247
 
    free(file[fd].fname);
248
 
    file[fd].fname = 0;
249
 
 
250
 
    return elio_close(file[fd].elio_fd);
251
 
    }
252
 
}
253
 
 
254
 
 
255
 
/**
256
 
 * Write the buffer to the file at the specified offset.
257
 
 * Return 0 on success, non-zero on failure
258
 
 */
259
 
int EAF_Write(int fd, eaf_off_t offset, const void *buf, size_t bytes)
260
 
{    
261
 
    double start = wall_time();
262
 
    Size_t rc;
263
 
 
264
 
    if (!valid_fd(fd)) return EAF_ERR_INVALID_FD;
265
 
 
266
 
    if (file[fd].size > 0) {
267
 
      if((offset+bytes)>file[fd].size){
268
 
#if 1
269
 
        printf("eaf_write failure: increase MA stack memory \n ");
270
 
        return EAF_ERR_WRITE;
271
 
#else
272
 
        rc=0;
273
 
        printf("eaf_write: offset %ld larger than MA size %ld ptr %p \n", (long)(offset+bytes), file[fd].size, file[fd].pointer);
274
 
        rc=eaf_flushbuf(fd, offset, buf, bytes);
275
 
        printf("eaf_write: from flushbug rc %d bytes %d\n ", rc, bytes);
276
 
#endif
277
 
      }else{
278
 
      memcpy(((char*)file[fd].pointer)+(long)offset, buf, bytes);
279
 
      rc=bytes;
280
 
      }
281
 
    }else{
282
 
    rc = elio_write(file[fd].elio_fd, (Off_t) offset, buf, (Size_t) bytes);
283
 
    }
284
 
    if (rc != ((Size_t)bytes)){
285
 
        printf("eaf_write: rc ne bytes %d bytes %d\n ", rc, bytes);
286
 
        if(rc < 0) return((int)rc); /* rc<0 means ELIO detected error */
287
 
        else return EAF_ERR_WRITE;
288
 
    }else {
289
 
        file[fd].nwrite++;
290
 
        file[fd].nb_write += bytes;
291
 
        file[fd].t_write += wall_time() - start;
292
 
 
293
 
        return EAF_OK;
294
 
    }
295
 
}
296
 
 
297
 
 
298
 
/**
299
 
 * Initiate an asynchronous write of the buffer to the file at the
300
 
 * specified offset.  Return in *req_id the ID of the request for
301
 
 * subsequent use in EAF_Wait/probe.  The buffer may not be reused until
302
 
 * the operation has completed.
303
 
 * Return 0 on success, non-zero on failure
304
 
 */
305
 
int EAF_Awrite(
306
 
        int fd, eaf_off_t offset, const void *buf, size_t bytes, int *req_id)
307
 
{
308
 
    double start = wall_time();
309
 
    io_request_t req;
310
 
    int rc;
311
 
 
312
 
    if (!valid_fd(fd)) return EAF_ERR_INVALID_FD;
313
 
 
314
 
    if (file[fd].size > 0) {
315
 
      if(offset>file[fd].size){
316
 
        rc=0;
317
 
        printf("eaf_awrite: offset %f larger than MA size %ld \n", offset, file[fd].size);
318
 
        return EAF_ERR_WRITE;
319
 
      }else{
320
 
      memcpy(((char*)file[fd].pointer)+(long)offset, buf, bytes);
321
 
      rc=bytes;
322
 
      }
323
 
    }else{
324
 
    rc = elio_awrite(file[fd].elio_fd, (Off_t)offset, buf, (Size_t)bytes, &req);
325
 
    }
326
 
    if(!rc){
327
 
        *req_id = req;
328
 
        file[fd].nawrite++;
329
 
        file[fd].nb_awrite += bytes;
330
 
    } 
331
 
    file[fd].t_awrite += wall_time() - start;
332
 
    return rc;
333
 
}
334
 
 
335
 
 
336
 
/**
337
 
 * Read the buffer from the specified offset in the file.
338
 
 * Return 0 on success, non-zero on failure
339
 
 */
340
 
int EAF_Read(int fd, eaf_off_t offset, void *buf, size_t bytes)
341
 
{
342
 
    double start = wall_time();
343
 
    Size_t rc;
344
 
 
345
 
    if (!valid_fd(fd)) return EAF_ERR_INVALID_FD;
346
 
    
347
 
    if (file[fd].size > 0) {
348
 
      if(offset>file[fd].size){
349
 
        rc=0;
350
 
        printf("eaf_read: offset %f larger than MA size %ld \n", offset, file[fd].size);
351
 
      }else{
352
 
      memcpy(buf, ((char*)file[fd].pointer)+(long)offset,  bytes);
353
 
      rc=bytes;
354
 
      }
355
 
    }else{
356
 
    rc = elio_read(file[fd].elio_fd, (Off_t) offset, buf, (Size_t) bytes);
357
 
    }
358
 
    if (rc != ((Size_t)bytes)){
359
 
        if(rc < 0) return((int)rc); /* rc<0 means ELIO detected error */
360
 
        else return EAF_ERR_READ;
361
 
    } else {
362
 
        file[fd].nread++;
363
 
        file[fd].nb_read += bytes;
364
 
        file[fd].t_read += wall_time() - start;
365
 
        return EAF_OK;
366
 
    }
367
 
}    
368
 
 
369
 
 
370
 
/**
371
 
 * Initiate an asynchronous read of the buffer from the file at the
372
 
 * specified offset.  Return in *req_id the ID of the request for
373
 
 * subsequent use in EAF_Wait/probe.  The buffer may not be reused until
374
 
 * the operation has completed.
375
 
 * Return 0 on success, non-zero on failure
376
 
 */
377
 
int EAF_Aread(int fd, eaf_off_t offset, void *buf, size_t bytes, int *req_id)
378
 
{
379
 
    double start = wall_time();
380
 
    io_request_t req;
381
 
    int rc;
382
 
 
383
 
    if (!valid_fd(fd)) return EAF_ERR_INVALID_FD;
384
 
 
385
 
    if (file[fd].size > 0) {
386
 
      if(offset>file[fd].size){
387
 
        rc=0;
388
 
        printf("eaf_aread: offset %f larger than MA size %ld \n", offset, file[fd].size);
389
 
        return EAF_ERR_READ;
390
 
      }else{
391
 
      memcpy(file[fd].pointer, buf, bytes);
392
 
      rc=0;
393
 
      }
394
 
    }else{
395
 
    rc = elio_aread(file[fd].elio_fd, (Off_t) offset, buf, (Size_t)bytes, &req);
396
 
    }
397
 
 
398
 
    if(!rc){
399
 
        *req_id = req;
400
 
        file[fd].naread++;
401
 
        file[fd].nb_aread += bytes;
402
 
    }
403
 
    file[fd].t_aread += wall_time() - start;
404
 
    return rc;
405
 
}
406
 
 
407
 
 
408
 
/**
409
 
 * Wait for the I/O operation referred to by req_id to complete.
410
 
 * Return 0 on success, non-zero on failure
411
 
 */
412
 
int EAF_Wait(int fd, int req_id)
413
 
{
414
 
    double start = wall_time();
415
 
    int code;
416
 
 
417
 
    io_request_t req = req_id;
418
 
    if (file[fd].size > 0) {
419
 
      /* got nothin' to do */
420
 
    }else{
421
 
    code = elio_wait(&req);
422
 
    }
423
 
    file[fd].t_wait += wall_time() - start;
424
 
    file[fd].nwait++;
425
 
 
426
 
    return code;
427
 
}
428
 
 
429
 
 
430
 
/**
431
 
 * status returns 0 if the I/O operation reffered to by req_id
432
 
 * is complete, 1 otherwise. 
433
 
 * Return 0 on success, non-zero on failure.
434
 
 */
435
 
int EAF_Probe(int req_id, int *status)
436
 
{
437
 
    io_request_t req = req_id;
438
 
    int rc;
439
 
#if 0
440
 
    if (file[fd].size > 0) {
441
 
      /* got nothin' to do */
442
 
      rc=0;
443
 
    }else{
444
 
    rc = elio_probe(&req, status);
445
 
    }
446
 
#else
447
 
    rc=0;
448
 
#endif
449
 
    if(!rc) *status = !(*status == ELIO_DONE);
450
 
    return rc;
451
 
}
452
 
 
453
 
 
454
 
/**
455
 
 * Delete the named file.  If the delete succeeds, or the file
456
 
 * does not exist, return 0.  Otherwise return non-zero.
457
 
 */
458
 
int EAF_Delete(const char *fname)
459
 
{
460
 
    /*
461
 
       if (access(fname, F_OK) == 0)
462
 
       if (unlink(fname))
463
 
       return EAF_ERR_UNLINK;
464
 
 
465
 
       return EAF_OK; 
466
 
       */
467
 
 
468
 
  int  j, found=0;
469
 
  /* get fd from fname */
470
 
  for (j=0; (j< EAF_MAX_FILES) && file[j].fname; j++){
471
 
      if(strcmp(file[j].fname,fname) == 0 && file[j].size >0) {
472
 
        found=1;
473
 
        break;
474
 
      }
475
 
    }
476
 
#ifdef DEBUG
477
 
  printf("eaf_delete: fname %s found %d \n", fname, found);
478
 
  if (found ==1) printf("eaf_delete: j %d filej.fname %s \n", j, file[j].fname);
479
 
#endif
480
 
    if (found > 0) {
481
 
       if(!MA_free_heap(file[j].handle)) {
482
 
         MA_summarize_allocated_blocks();
483
 
         return EAF_ERR_UNLINK;
484
 
       }
485
 
       else
486
 
         file[j].fname= NULL;
487
 
           return EAF_OK;
488
 
       }else{
489
 
    /* Now that ELIO files can have extents must call its
490
 
       routine to delete files */
491
 
 
492
 
  if (elio_delete(fname) == ELIO_OK)
493
 
    return EAF_OK;
494
 
  else
495
 
    return EAF_ERR_UNLINK;
496
 
    }
497
 
}
498
 
 
499
 
 
500
 
/**
501
 
 * Return in *avail_mb and *fstype the amount of free space (in Mb)
502
 
 * and filesystem type (currenly UFS, PFS, or PIOFS) of the filesystem
503
 
 * associated with path.  Path should be either a filename, or a directory
504
 
 * name ending in a slash (/).  fslen should specify the size of the
505
 
 * buffer pointed to by fstype.
506
 
 *
507
 
 * Return 0 on success, non-zero on failure.
508
 
 */
509
 
int EAF_Stat(const char *path, int *avail_mb, char *fstype, int fslen)
510
 
{
511
 
    char dirname[PATH_MAX];
512
 
    stat_t statinfo;
513
 
    int rc;
514
 
 
515
 
    if ((rc = elio_dirname(path, dirname, sizeof(dirname)))) return rc;
516
 
    if ((rc = elio_stat(dirname, &statinfo))) return rc;
517
 
    if (fslen < 8) return EAF_ERR_TOO_SHORT;
518
 
 
519
 
    *avail_mb = (int)(statinfo.avail>>10);
520
 
    if (statinfo.fs == ELIO_UFS)
521
 
        strcpy(fstype, "UFS");
522
 
    else if (statinfo.fs == ELIO_PFS)
523
 
        strcpy(fstype, "PFS");
524
 
    else if (statinfo.fs == ELIO_PIOFS)
525
 
        strcpy(fstype, "PIOFS");
526
 
    else
527
 
        strcpy(fstype, "UNKNOWN");
528
 
 
529
 
    return EAF_OK;
530
 
}
531
 
 
532
 
 
533
 
/**
534
 
 * Return 0 if code corresponds to EOF, or non-zero.
535
 
 */
536
 
int EAF_Eof(int code)
537
 
{
538
 
    return !(code == EAF_ERR_EOF);
539
 
}
540
 
 
541
 
 
542
 
/**
543
 
 * Return in msg (assumed to hold up to 80 characters)
544
 
 * a description of the error code obtained from an EAF call,
545
 
 * or an empty string if there is no such code
546
 
 */
547
 
void EAF_Errmsg(int code, char *msg)
548
 
{
549
 
    if (code == EAF_OK) 
550
 
        (void) strcpy(msg, "OK");
551
 
    else if (code == EAF_ERR_EOF) 
552
 
        (void) strcpy(msg, "end of file");
553
 
    else if (code == EAF_ERR_MAX_OPEN)
554
 
        (void) strcpy(msg, "too many open files");
555
 
    else if (code == EAF_ERR_MEMORY)
556
 
        (void) strcpy(msg, "memory allocation failed");
557
 
    else if (code == EAF_ERR_OPEN)
558
 
        (void) strcpy(msg, "failed opening file");
559
 
    else if (code == EAF_ERR_CLOSE)
560
 
        (void) strcpy(msg, "failed closing file");
561
 
    else if (code == EAF_ERR_INVALID_FD)
562
 
        (void) strcpy(msg, "invalid file descriptor");
563
 
    else if (code == EAF_ERR_WRITE)
564
 
        (void) strcpy(msg, "write failed");
565
 
    else if (code == EAF_ERR_AWRITE)
566
 
        (void) strcpy(msg, "asynchronous write failed");
567
 
    else if (code == EAF_ERR_READ)
568
 
        (void) strcpy(msg, "read failed");
569
 
    else if (code == EAF_ERR_AREAD)
570
 
        (void) strcpy(msg, "asynchronous read failed");
571
 
    else if (code == EAF_ERR_WAIT)
572
 
        (void) strcpy(msg, "wait failed");
573
 
    else if (code == EAF_ERR_PROBE)
574
 
        (void) strcpy(msg, "probe failed");
575
 
    else if (code == EAF_ERR_UNLINK)
576
 
        (void) strcpy(msg, "unlink failed");
577
 
    else if (code == EAF_ERR_UNIMPLEMENTED)
578
 
        (void) strcpy(msg, "unimplemented operation");
579
 
    else if (code == EAF_ERR_STAT)
580
 
        (void) strcpy(msg, "stat failed");
581
 
    else if (code == EAF_ERR_TOO_SHORT)
582
 
        (void) strcpy(msg, "an argument string/buffer is too short");
583
 
    else if (code == EAF_ERR_TOO_LONG)
584
 
        (void) strcpy(msg, "an argument string/buffer is too long");
585
 
    else if (code == EAF_ERR_NONINTEGER_OFFSET)
586
 
        (void) strcpy(msg, "offset is not an integer");
587
 
    else if (code == EAF_ERR_TRUNCATE)
588
 
        (void) strcpy(msg, "truncate failed");
589
 
    else 
590
 
        elio_errmsg(code, msg);
591
 
}
592
 
 
593
 
 
594
 
/**
595
 
 * Truncate the file to the specified length.
596
 
 * Return 0 on success, non-zero otherwise.
597
 
 */
598
 
int EAF_Truncate(int fd, eaf_off_t length)
599
 
{
600
 
#ifdef CRAY 
601
 
    int rc;
602
 
#endif
603
 
 
604
 
    if (!valid_fd(fd)) return EAF_ERR_INVALID_FD;
605
 
 
606
 
#ifdef CRAY 
607
 
    /* ftruncate does not work with Cray FFIO, we need to implement it
608
 
     * as a sequence of generic close, truncate, open calls 
609
 
     */
610
 
 
611
 
    rc = elio_close(file[fd].elio_fd);
612
 
    if(rc) return rc;
613
 
    if(truncate(file[fd].fname, (off_t) length)) return EAF_ERR_TRUNCATE;  
614
 
    if (!(file[fd].elio_fd = elio_open(file[fd].fname, file[fd].type, ELIO_PRIVATE))) {
615
 
        free(file[fd].fname);
616
 
        file[fd].fname = 0;
617
 
        return ELIO_PENDING_ERR;
618
 
    }
619
 
#else
620
 
    if(elio_truncate(file[fd].elio_fd, (Off_t)length)) return EAF_ERR_TRUNCATE;
621
 
#endif
622
 
 
623
 
    return EAF_OK;
624
 
    /*  return elio_truncate(file[fd].elio_fd, (Off_t) length);*/
625
 
}
626
 
 
627
 
 
628
 
/**
629
 
 * Return in length the length of the file.  
630
 
 * Return 0 on success, nonzero on failure.
631
 
 */
632
 
int EAF_Length(int fd, eaf_off_t *length)
633
 
{
634
 
    Off_t len;
635
 
    int rc;
636
 
 
637
 
    if (!valid_fd(fd)) return EAF_ERR_INVALID_FD;
638
 
 
639
 
    if (file[fd].size > 0) {
640
 
      // should be in MB???
641
 
      if(file[fd].openma == 0)  return EAF_ERR_INVALID_FD;
642
 
      len=file[fd].size;
643
 
      rc=0;
644
 
    }else{
645
 
    rc = elio_length(file[fd].elio_fd, &len);
646
 
    }
647
 
    if(!rc) *length = (eaf_off_t) len;
648
 
    return rc;
649
 
}
650
 
 
651
 
 
652
 
/**
653
 
 * Print performance statistics for this file to standard output
654
 
 */
655
 
void EAF_Print_stats(int fd)
656
 
{
657
 
    eaf_off_t len;
658
 
    double mbr, mbw, mbra, mbwa;
659
 
    if (!valid_fd(fd)) return;
660
 
 
661
 
    if (EAF_Length(fd, &len)) len = -1;
662
 
 
663
 
    printf("\n");
664
 
    printf("------------------------------------------------------------\n");
665
 
#if HAVE_UNSIGNED_LONG_LONG_INT
666
 
    printf("EAF file %d: \"%s\" size=%llu bytes\n", 
667
 
            fd, file[fd].fname, (unsigned long long) len);
668
 
#else
669
 
    printf("EAF file %d: \"%s\" size=%lu bytes\n", 
670
 
            fd, file[fd].fname, (unsigned long) len);
671
 
#endif
672
 
    printf("------------------------------------------------------------\n");
673
 
    printf("               write      read    awrite     aread      wait\n");
674
 
    printf("               -----      ----    ------     -----      ----\n");
675
 
    printf("     calls: %8d  %8d  %8d  %8d  %8d\n", 
676
 
            file[fd].nwrite, file[fd].nread, file[fd].nawrite, 
677
 
            file[fd].naread, file[fd].nwait);
678
 
    printf("   data(b): %.2e  %.2e  %.2e  %.2e\n",
679
 
            file[fd].nb_write, file[fd].nb_read, file[fd].nb_awrite, 
680
 
            file[fd].nb_aread);
681
 
    printf("   time(s): %.2e  %.2e  %.2e  %.2e  %.2e\n",
682
 
            file[fd].t_write, file[fd].t_read, 
683
 
            file[fd].t_awrite, file[fd].t_aread, 
684
 
            file[fd].t_wait);
685
 
    mbr = 0.0;
686
 
    mbw = 0.0;
687
 
    mbwa= 0.0;
688
 
    mbra= 0.0;
689
 
    if (file[fd].t_write > 0.0) mbw = file[fd].nb_write/(1e6*file[fd].t_write);
690
 
    if (file[fd].t_read  > 0.0) mbr = file[fd].nb_read/(1e6*file[fd].t_read);
691
 
    if ((file[fd].t_wait + file[fd].t_aread) > 0.0) 
692
 
        mbra = 1e-6*file[fd].nb_aread / 
693
 
            (file[fd].t_wait + file[fd].t_aread);
694
 
    if ((file[fd].t_wait + file[fd].t_awrite) > 0.0) 
695
 
        mbwa = 1e-6*file[fd].nb_awrite / 
696
 
            (file[fd].t_wait + file[fd].t_awrite);
697
 
 
698
 
    /* Note that wait time does not distinguish between read/write completion 
699
 
       so that entire wait time is counted 
700
 
       in computing effective speed for async read & write */
701
 
    if (mbwa+mbra) {
702
 
        printf("rate(mb/s): %.2e  %.2e  %.2e* %.2e*\n", mbw, mbr, mbwa, mbra);
703
 
        printf("------------------------------------------------------------\n");
704
 
        printf("* = Effective rate.  Full wait time used for read and write.\n\n");
705
 
    }
706
 
    else {
707
 
        printf("rate(mb/s): %.2e  %.2e\n", mbw, mbr);
708
 
        printf("------------------------------------------------------------\n\n");
709
 
    }
710
 
    fflush(stdout);
711
 
}
712
 
 
713
 
int eaf_flushbuf(int fd, eaf_off_t offset, const void *buf, size_t bytes)
714
 
     /* once we run out of MA memory, let's open a real eaf file,
715
 
        flush the whole MA allocation to the file, plus the last bytes 
716
 
      */
717
 
{
718
 
  int rc, fd_new;
719
 
  long masize, mahandle;
720
 
  char *mapointer, *oldfname;
721
 
  double start = wall_time();
722
 
  /* invalidate old FD but do not deallocate MA */
723
 
  masize=file[fd].size;
724
 
  mahandle=file[fd].handle;
725
 
  mapointer=file[fd].pointer;
726
 
  oldfname = malloc((unsigned) (strlen(file[fd].fname)));
727
 
  strcpy(oldfname, file[fd].fname);
728
 
  file[fd].fname= NULL;
729
 
  rc=EAF_Open(oldfname, EAF_RW, &fd_new);
730
 
  (void) free(oldfname);
731
 
    if (rc !=0 ) {
732
 
      printf(" flushbuf: open failure \n");
733
 
      return rc;
734
 
    }
735
 
    /* flush MA */
736
 
    rc = elio_write(file[fd_new].elio_fd, 0., (char*)mapointer, (Size_t) masize);
737
 
    /* write last bytes */
738
 
    rc = elio_write(file[fd_new].elio_fd, (Off_t) file[fd].size , buf, (Size_t) bytes);
739
 
    if (rc != bytes){
740
 
      printf(" flushbuf: write failure \n");
741
 
        if(rc < 0) return((int)rc); /* rc<0 means ELIO detected error */
742
 
        else return EAF_ERR_WRITE;
743
 
    }else {
744
 
        file[fd_new].nwrite++;
745
 
        file[fd_new].nb_write += file[fd].size;
746
 
        file[fd_new].nwrite++;
747
 
        file[fd_new].nb_write += bytes;
748
 
        file[fd_new].t_write += wall_time() - start;
749
 
    }
750
 
    if(!MA_free_heap(mahandle)) {
751
 
      MA_summarize_allocated_blocks();
752
 
      return EAF_ERR_UNLINK;
753
 
    }
754
 
  /* swap fd with fd_new, is this too little?? */
755
 
  fd = fd_new;
756
 
 
757
 
  return rc;
758
 
}