src/hdf5/H5ecloud/H5Part.c

Go to the documentation of this file.
00001 #include <stdio.h>
00002 #include <stdlib.h>
00003 #include <string.h>
00004 #include <hdf5.h>
00005 #include "H5Part.h"
00006 
00007 #ifdef IPPL_XT3
00008 # define SEEK_END 2 
00009 #endif
00010 
00011 static unsigned h5part_debug=0;
00012 
00013 /********* Private Function Declarations *************/
00014 herr_t H5PartIOcounter(hid_t group_id,
00015                    const char *member_name,
00016                    void *operator_data);
00017 
00018 /********** Definitions of Functions/Subroutines ******/
00019 
00020 /*========== File Opening/Closing ===============*/
00021 /*
00022   H5PartOpenFile:  Opens file with specified filename. 
00023     If you open with flag H5PART_WRITE, it will truncate any
00024     file with the specified filename and start writing to it.
00025     If you open with H5PART_READ, then it will open the file
00026     readonly.  I could probably do an APPEND mode as well, but
00027     just haven't done so yet.  APPEND would need to check the
00028     file to determine its current state and modify the 
00029     H5PartFile datastructure accordingly.
00030 
00031     H5PartFile should be treated as an essentially opaque
00032     datastructure.  It acts as the file handle, but internally
00033     it maintains several key state variables associated with 
00034     the file.
00035 */
00036 
00037 H5PartFile *H5PartOpenFileParallel(const char *filename,unsigned flags
00038 #ifdef PARALLEL_IO
00039                 ,                  MPI_Comm comm
00040 #endif
00041 ){
00042   H5PartFile *f=(H5PartFile*)malloc(sizeof(H5PartFile));
00043 #ifdef PARALLEL_IO
00044   MPI_Info info = MPI_INFO_NULL; /* for the SP2... perhaps different for linux */
00045 #endif
00046   f->xfer_prop = f->create_prop = f->access_prop=H5P_DEFAULT;
00047 #ifdef PARALLEL_IO
00048   MPI_Comm_size(comm,&f->nprocs);
00049   MPI_Comm_rank(comm,&f->myproc);
00050   f->pnparticles=(long long*)malloc(sizeof(long long)*f->nprocs);
00051   /* access_prop: properties like chunking or parallel I/O */
00052   f->access_prop = H5Pcreate(H5P_FILE_ACCESS);
00053   if(H5Pset_fapl_mpio(f->access_prop,comm,info)<0){
00054         fprintf(stderr,"Total failure trying to setup mpi-io for access\n");
00055         exit(0);
00056   }
00057   /* create_prop: tunable parameters like blocksize and btree sizes */
00058   /* f->create_prop = H5Pcreate(H5P_FILE_CREATE); */
00059   f->create_prop = H5P_DEFAULT;
00060   /* currently create_prop is empty */
00061   /* xfer_prop:  also used for parallel I/O, during actual writes
00062           rather than the access_prop which is for file creation. */
00063   f->xfer_prop = H5Pcreate(H5P_DATASET_XFER);
00064   H5Pset_dxpl_mpio(f->xfer_prop,H5FD_MPIO_COLLECTIVE);
00065   f->comm = comm;
00066 #endif
00067   if(flags==H5PART_READ){
00068     f->file=H5Fopen(filename,H5F_ACC_RDONLY,f->access_prop);
00069     /* just do this serially 
00070        f->file = H5Fopen(filename,H5F_ACC_RDONLY,H5P_DEFAULT); */
00071   }
00072   else if(flags==H5PART_WRITE){
00073     f->file=H5Fcreate(filename,H5F_ACC_TRUNC,f->create_prop,f->access_prop);
00074   }
00075   else {
00076     f->file=-1;
00077     fprintf(stderr,"H5Open: Invalid file access type %d\n",flags);
00078   }
00079   if(f->file<=0) {
00080     free(f);
00081     fprintf(stderr,"H5Open: File open failed for file [%s]\n",
00082             filename);
00083         exit(0); 
00084         return 0;
00085   }
00086 #ifdef PARALLEL_IO
00087   else {
00088         if(h5part_debug) fprintf(stderr,"Proc[%u] Opened file %s val=%d\n",
00089                 f->myproc,filename,f->file);
00090   }
00091 #endif
00092   f->mode=flags;
00093   f->maxstep=0;
00094   f->timegroup=0;
00095   f->timestep=0;
00096   f->shape=0;
00097   f->diskshape=H5S_ALL;
00098   f->memshape=H5S_ALL;
00099   f->viewstart=-1;
00100   f->viewend=-1;
00101   return f;
00102 }
00103 
00104 H5PartFile *H5PartOpenFile(const char *filename,unsigned flags){
00105   H5PartFile *f=(H5PartFile*)malloc(sizeof(H5PartFile));
00106   /* printf("filename is [%s] flags=%0X\n",filename,flags); */
00107   
00108   f->xfer_prop = f->create_prop = f->access_prop=H5P_DEFAULT;
00109 #ifdef PARALLEL_IO
00110   f->pnparticles=0;
00111   f->comm = MPI_COMM_WORLD;
00112   f->nprocs=1;
00113   f->myproc=0;
00114 #endif
00115   if(flags==H5PART_READ){
00116     /*  f->file=H5Fopen(filename,H5F_ACC_RDONLY,f->access_prop); */
00117     /* just do this serially */
00118     f->file = H5Fopen(filename,H5F_ACC_RDONLY,H5P_DEFAULT);
00119     if(f->file==-1){
00120       fprintf(stderr,"H5Open: File %s not found\n",filename);
00121     }
00122   }
00123   else if(flags==H5PART_WRITE){
00124     f->file=H5Fcreate(filename,H5F_ACC_TRUNC,H5P_DEFAULT,H5P_DEFAULT);
00125   }
00126   else {
00127     f->file=-1;
00128     fprintf(stderr,"H5Open: Invalid file access type %d\n",flags);
00129   }
00130   if(f->file<0) {
00131     free(f);
00132     fprintf(stderr,"H5Open: File open failed for file [%s]\n",
00133             filename);
00134     return 0;
00135   }
00136   f->mode=flags;
00137   f->maxstep=0;
00138   f->timegroup=0;
00139   f->timestep=0;
00140   f->shape=0;
00141   f->diskshape=H5S_ALL;
00142   f->memshape=H5S_ALL;
00143   f->viewstart=-1;
00144   f->viewend=-1;
00145   return f;
00146 }
00147 int H5PartFileIsValid(H5PartFile *f){
00148   if(f->file > 0) return 1;
00149   else return 0;
00150 }
00151 /*
00152   H5PartCloseFile:  Does what it says it does.
00153 */
00154 void H5PartCloseFile(H5PartFile *f){
00155   if(f->shape>0) H5Sclose(f->shape); f->shape=0;
00156   if(f->timegroup>0) H5Gclose(f->timegroup); f->timegroup=0;
00157   if(f->diskshape!=H5S_ALL) H5Sclose(f->diskshape);
00158 #ifdef PARALLEL_IO
00159   if(f->pnparticles) free(f->pnparticles);
00160 #endif
00161   if(f->xfer_prop!=H5P_DEFAULT) {
00162     H5Pclose(f->xfer_prop); f->xfer_prop=H5P_DEFAULT;
00163   }
00164   if(f->access_prop!=H5P_DEFAULT) {
00165     H5Pclose(f->access_prop); f->access_prop=H5P_DEFAULT;
00166   }  
00167   if(f->create_prop!=H5P_DEFAULT) {
00168     H5Pclose(f->create_prop); f->create_prop=H5P_DEFAULT;
00169   }
00170   if(f->file) H5Fclose(f->file); f->file=0;
00171   free(f);
00172 }
00173 
00174 
00175 /*============== File Writing Functions ==================== */
00176 /*
00177   H5PartSetNumParticles:  This is a private function used by the 
00178   other functions that write arrays.  Its sole purpose is to 
00179   prevent needless creation of new HDF5 DataSpace handles if
00180   the number of particles is invariant throughout the sim.
00181   That's its only reason for existence.
00182 */
00183 void H5PartSetNumParticles(H5PartFile *f,long long nparticles){
00184   hssize_t start[1];
00185   hsize_t stride[1],count[1],total;
00186   register int i,r;
00187   /*  printf("Set Number of Particles to %lld\n",nparticles); */
00188 #ifndef PARALLEL_IO
00189   /* if we are not using parallel-IO, there is enough information
00190      to know that we can short circuit this routine.  However,
00191      for parallel IO, this is going to cause problems because
00192      we don't know if things have changed globally */
00193   if(f->nparticles==nparticles) return;  /* no change  */
00194 #endif
00195   if(f->diskshape!=H5S_ALL) H5Sclose(f->diskshape);
00196   if(f->memshape!=H5S_ALL) H5Sclose(f->memshape);
00197   f->memshape=f->diskshape = H5S_ALL;
00198   if(f->shape) H5Sclose(f->shape);
00199   f->nparticles=(hsize_t)nparticles;
00200 #ifndef PARALLEL_IO
00201   f->shape=H5Screate_simple(1, /* 1 dimensional shape */
00202                             &(f->nparticles), /* with nparticles elements */
00203                             NULL); /* ignore this :-) */
00204 #else /* PARALLEL_IO */
00205   /* The Gameplan here is to declare the overall size of the on-disk
00206      data structure the same way we do for the serial case.  But
00207      then we must have additional "DataSpace" structures to define
00208      our in-memory layout of our domain-decomposed portion of the particle
00209      list as well as a "selection" of a subset of the on-disk 
00210      data layout that will be written in parallel to mutually exclusive
00211      regions by all of the processors during a parallel I/O operation.
00212      These are f->shape, f->memshape and f->diskshape respectively. */
00213   /* acquire the number of particles to be written from each MPI process */
00214   MPI_Allgather(&nparticles,1,MPI_LONG_LONG,f->pnparticles,1,MPI_LONG_LONG,f->comm);
00215 
00216   if(f->myproc==0 && h5part_debug){
00217         puts("AllGather:  Particle offsets:\n");
00218         for(i=0;i<f->nprocs;i++) 
00219                 printf("\tnp=%u\n",f->pnparticles[i]); /* compute total nparticles */
00220   }
00221   /* should I create a selection here? */
00222   stride[0]=1;
00223   start[0]=0;
00224   for(i=0;i<f->myproc;i++) start[0]+=f->pnparticles[i]; /* compute start offsets */
00225   total=0;
00226   for(i=0;i<f->nprocs;i++) total+=f->pnparticles[i]; /* compute total nparticles */
00227   f->shape = H5Screate_simple(1,&total,&total); /* declare overall datasize */
00228   f->diskshape = H5Screate_simple(1,&total,&total); /* declare overall data size  but then will select a subset */
00229   {
00230     hsize_t dmax=H5S_UNLIMITED;
00231     f->memshape = H5Screate_simple(1,&(f->nparticles),&dmax); /* declare local memory datasize */
00232   }
00233 
00234   if(f->shape<0 || f->memshape<0 || f->diskshape<0){
00235         fprintf(stderr,"Abort:  shape construction failed\n");
00236         if(f->shape<0) fprintf(stderr,"\tf->shape\n");
00237         if(f->diskshape<0) fprintf(stderr,"\tf->diskshape\n");
00238         if(f->memshape<0) fprintf(stderr,"\tf->memshape\n");
00239         exit(0);
00240 }
00241   count[0]=nparticles; /* based on local nparticles (for the selection */
00242   /* and then set the subset of the data you will write to */
00243   r=H5Sselect_hyperslab(f->diskshape,H5S_SELECT_SET,start,stride,count,NULL);
00244   if(r<0){
00245         fprintf(stderr,"Abort: Selection Failed!\n");
00246         exit(0);
00247   }
00248   if(f->timegroup<0){
00249     H5PartSetStep(f,0);
00250   }
00251 #endif
00252 }
00253 
00254 /*
00255   H5PartWriteArray:  This writes an individual array of data
00256     for a given timestep.  It probably would be convenient if this
00257     were public, but its private because it there are some order/
00258     state dependencies that get kind of nasty to manage (and therefore
00259     are not managed).  It is otherwise assuming that the timegroup
00260     has already been created and other such details.
00261     It is called by the mongo H5PartWriteStep() routine.
00262  */
00263 int H5PartWriteDataFloat64(H5PartFile *f,char *name,double *array){
00264   register int r;
00265   hid_t dataset;
00266  if(f->mode==H5PART_READ){
00267         fprintf(stderr,"H5PartWriteDataFloat64:  Error!  Attempting to write to read-only file\n");
00268         return 0;
00269   }
00270   /* fprintf(stderr,"Create a dataset[%s]  mounted on the timegroup %u\n",
00271          name,f->timestep); */
00272   if(f->timegroup<=0) {fprintf(stderr,"Eeeerrrrroooorrrr!!!!\n");}
00273   dataset = H5Dcreate(f->timegroup,name,H5T_NATIVE_DOUBLE,f->shape,H5P_DEFAULT);
00274   if(dataset<0)
00275     fprintf(stderr,"Dataset open failed for name=[%s] step=%u!\n",
00276             name,f->timestep);
00277   r=H5Dwrite(dataset,H5T_NATIVE_DOUBLE,f->memshape,f->diskshape,H5P_DEFAULT,array);
00278   H5Dclose(dataset);
00279   return r;
00280 }
00281 int H5PartWriteDataInt64(H5PartFile *f,char *name,long long *array){
00282   register int r;
00283   hid_t dataset;
00284   /*fprintf(stderr,"Create a dataset[%s]  mounted on the timegroup %u\n",
00285          name,f->timestep); */
00286  if(f->mode==H5PART_READ){
00287         fprintf(stderr,"H5PartWriteDataFloat64:  Error!  Attempting to write to read-only file\n");
00288         return 0;
00289   }
00290   if(f->timegroup<=0) {fprintf(stderr,"Eeeerrrrroooorrrr!!!!\n");}
00291   dataset = H5Dcreate(f->timegroup,name,H5T_NATIVE_INT64,f->shape,H5P_DEFAULT);
00292   if(dataset<0){
00293     fprintf(stderr,"Dataset open failed for name=[%s] step=%u!\n",
00294             name,f->timestep);
00295     exit(0);
00296   }
00297   r=H5Dwrite(dataset,H5T_NATIVE_INT64,f->memshape,f->diskshape,H5P_DEFAULT,array);
00298   if(r<0) {
00299         fprintf(stderr,"Attempt to write dataset failed!\n");
00300         exit(0);
00301   }
00302   H5Dclose(dataset);
00303   return r;
00304 }
00305 int H5PartWriteFileAttribString(H5PartFile *f,char *name,
00306                                 char *attrib){
00307  if(f->mode==H5PART_READ){
00308         fprintf(stderr,"H5PartWriteDataFloat64:  Error!  Attempting to write to read-only file\n");
00309         return 0;
00310   }
00311   return H5PartWriteFileAttrib(f,name,H5T_NATIVE_CHAR,attrib,strlen(attrib)+1);
00312 }
00313 int H5PartWriteStepAttribString(H5PartFile *f,char *name,
00314                                 char *attrib){
00315  if(f->mode==H5PART_READ){
00316         fprintf(stderr,"H5PartWriteDataFloat64:  Error!  Attempting to write to read-only file\n");
00317         return 0;
00318   }
00319   return H5PartWriteStepAttrib(f,name,H5T_NATIVE_CHAR,attrib,strlen(attrib)+1);
00320 }
00321 int H5PartWriteStepAttrib(H5PartFile *f,char *name,
00322                           hid_t type,void *value,int nelem){
00323   register int r;
00324   hid_t attrib;
00325   hid_t space;
00326   hsize_t len;
00327  if(f->mode==H5PART_READ){
00328         fprintf(stderr,"H5PartWriteDataFloat64:  Error!  Attempting to write to read-only file\n");
00329         return 0;
00330   }
00331   /*fprintf(stderr,"Create a attribute[%s]  mounted on the timegroup %u\n",
00332          name,f->timestep); */
00333   if(f->timegroup<=0) {fprintf(stderr,"Eeeerrrrroooorrrr!!!!\n");}
00334   len = nelem;
00335   space = H5Screate_simple(1,&len,NULL);
00336   attrib = H5Acreate(f->timegroup,name,type,space,H5P_DEFAULT);
00337   r=H5Awrite(attrib,type,value);
00338   H5Aclose(attrib);
00339   H5Sclose(space);
00340   return r;
00341 }
00342 
00343 int H5PartWriteAttrib(H5PartFile *f,char *name,
00344     hid_t type,void *value,int nelem){
00345  if(f->mode==H5PART_READ){
00346         fprintf(stderr,"H5PartWriteDataFloat64:  Error!  Attempting to write to read-only file\n");
00347         return 0;
00348   }
00349     return H5PartWriteStepAttrib(f,name,type,value,nelem);
00350 }
00351 
00352 
00353 int H5PartWriteFileAttrib(H5PartFile *f,char *name,
00354                           hid_t type,void *value,int nelem){
00355   register int r;
00356   hid_t attrib,rootgroup;
00357   hid_t space;
00358   hsize_t len;
00359  if(f->mode==H5PART_READ){
00360         fprintf(stderr,"H5PartWriteDataFloat64:  Error!  Attempting to write to read-only file\n");
00361         return 0;
00362   }
00363  if(h5part_debug) fprintf(stderr,"Create a File attribute[%s] step=%u\n",
00364                           name,f->timestep);
00365   if(f->file<=0) {
00366     fprintf(stderr,"Eeeerrrrroooorrrr!!!! File is not open!\n");
00367     return 0;
00368   }
00369   len = nelem;
00370   space = H5Screate_simple(1,&len,NULL); 
00371   if(space<=0) { 
00372     fprintf(stderr,"Eeeerrrrroooorrrr!!!! Could not create space with len!\n",(unsigned)len);
00373     return 0;
00374   }
00375   rootgroup = H5Gopen(f->file,"/");
00376   attrib = H5Acreate(rootgroup,name,type,space,H5P_DEFAULT);
00377   H5Gclose(rootgroup);
00378   if(attrib<=0) { 
00379     fprintf(stderr,"Eeeerrrrroooorrrr!!!! Attribute Creation Failed!\n");
00380     return 0;
00381   }
00382   r=H5Awrite(attrib,type,value);
00383   H5Aclose(attrib);
00384   H5Sclose(space);
00385   return r;
00386 }
00387 herr_t H5PartAttribcounter(hid_t group_id,
00388                    const char *member_name,
00389                    void *operator_data){
00390   int *count = (int*)operator_data;
00391   (*count)++;
00392   return 0;
00393 }
00394 int H5PartGetNumStepAttribs(H5PartFile *f){ /* for current filestep */
00395   return H5Aget_num_attrs(f->timegroup);
00396 }
00397 int H5PartGetNumFileAttribs(H5PartFile *f){
00398   /* must walk the attributes */
00399   /* iterate to get numsteps */
00400   int nattribs;
00401   hid_t rootgroup=H5Gopen(f->file,"/");;
00402   nattribs=H5Aget_num_attrs(rootgroup); /* open / for the file?
00403                                        or is there a problem with 
00404                                        file attributes? */
00405   H5Gclose(rootgroup);
00406   return nattribs;
00407 }
00408 
00409 hid_t H5PartNormType(hid_t type){
00410   H5T_class_t tclass = H5Tget_class(type);
00411   int size = H5Tget_size(type);
00412   switch(tclass){
00413   case H5T_INTEGER:
00414     if(size==8) return H5T_NATIVE_INT64;
00415     else if(size==1) return H5T_NATIVE_CHAR;
00416     else fprintf(stderr,"Unknown type %u.  Cannot infer normalized type\n",type);
00417     break;
00418   case H5T_FLOAT:
00419     return H5T_NATIVE_DOUBLE;
00420     break;
00421   }
00422   return -1;
00423 }
00424 
00425 void H5PartGetStepAttribInfo(H5PartFile *f,int idx,
00426                          char *name,size_t maxname,hid_t *type,int *nelem){
00427   hid_t attrib=H5Aopen_idx(f->timegroup,idx);
00428   hid_t mytype=H5Aget_type(attrib);
00429   hid_t space = H5Aget_space(attrib);
00430   if(nelem)
00431     *nelem=H5Sget_simple_extent_npoints(space);
00432   if(name)
00433     H5Aget_name(attrib,maxname,name);
00434   if(type)
00435     *type=H5PartNormType(mytype); /* normalize the type to be machine-native
00436                                  this means one of 
00437                                 H5T_NATIVE_DOUBLE
00438                                 H5T_NATIVE_INT64
00439                                 H5T_NATIVE_CHAR */
00440   H5Sclose(space);
00441   H5Tclose(mytype);
00442   H5Aclose(attrib);
00443 }
00444 void H5PartGetFileAttribInfo(H5PartFile *f,int idx,
00445                          char *name,size_t maxname,hid_t *type,int *nelem){
00446   hid_t attrib=H5Aopen_idx(f->file,idx);
00447   hid_t mytype=H5Aget_type(attrib);
00448   hid_t space = H5Aget_space(attrib);
00449   if(nelem)
00450     *nelem=H5Sget_simple_extent_npoints(space);
00451   if(name)
00452     H5Aget_name(attrib,maxname,name);
00453   if(type)
00454     *type=H5PartNormType(mytype); /* normalize the type to be machine-native
00455                                  this means one of 
00456                                 H5T_NATIVE_DOUBLE
00457                                 H5T_NATIVE_INT64
00458                                 H5T_NATIVE_CHAR */
00459   H5Sclose(space);
00460   H5Tclose(mytype);
00461   H5Aclose(attrib);
00462 }
00463 
00464 int H5PartReadStepAttrib(H5PartFile *f,char *name,void *data){
00465   /* use the open attribute by name mode of operation */
00466   hid_t attrib=H5Aopen_name(f->timegroup,name);
00467   hid_t mytype;
00468   hid_t space;
00469   hsize_t nelem;
00470   hid_t type;
00471 
00472   if(attrib<=0) return -1;
00473   mytype=H5Aget_type(attrib);
00474   space = H5Aget_space(attrib);
00475   nelem=H5Sget_simple_extent_npoints(space);
00476   type=H5PartNormType(mytype); /* normalize the type to be machine-native
00477                                  this means one of 
00478                                 H5T_NATIVE_DOUBLE
00479                                 H5T_NATIVE_INT64
00480                                 H5T_NATIVE_CHAR */
00481   H5Aread(attrib,type,data);
00482   H5Sclose(space);
00483   H5Tclose(mytype);
00484   H5Aclose(attrib);
00485   return 1;
00486 }
00487 
00488 void H5PartReadAttrib(H5PartFile *f,char *name,void *data){
00489     /* use the open attribute by name mode of operation */
00490     H5PartReadStepAttrib(f,name,data);
00491 }
00492 
00493 
00494 
00495 
00496 int H5PartReadFileAttrib(H5PartFile *f,char *name,void *data){
00497   hid_t attrib=H5Aopen_name(f->file,name);
00498   hid_t mytype;
00499   hid_t space;
00500   hsize_t nelem;
00501   hid_t type;
00502   if(attrib<0) return -1;
00503   mytype=H5Aget_type(attrib);
00504   space = H5Aget_space(attrib);
00505   nelem=H5Sget_simple_extent_npoints(space);
00506   type=H5PartNormType(mytype); /* normalize the type to be machine-native
00507                                  this means one of 
00508                                 H5T_NATIVE_DOUBLE
00509                                 H5T_NATIVE_INT64
00510                                 H5T_NATIVE_CHAR */
00511   H5Aread(attrib,type,data);
00512   H5Sclose(space);
00513   H5Tclose(mytype);
00514   H5Aclose(attrib);
00515   return 1;
00516 }
00517 
00518 
00519 /*================== File Reading Routines =================*/
00520 /*
00521   H5PartSetStep:  This routine is *only* useful when you are reading
00522   data.  Using it while you are writing will generate nonsense results!
00523   (This file format is only half-baked... robustness is not std equipment!)
00524   So you use this to random-access the file for a particular timestep.
00525   Failure to explicitly set the timestep on each read will leave you
00526   stuck on the same timestep for *all* of your reads.  That is to say
00527   the writes auto-advance the file pointer, but the reads do not
00528   (they require explicit advancing by selecting a particular timestep).
00529 */
00530 void H5PartSetStep(H5PartFile *f,int step){
00531   char name[128];
00532 #ifdef PARALLEL_IO
00533   if(h5part_debug) printf("Proc[%u] SetStep to %u for file %u\n",f->myproc,step,f->file);
00534 #else
00535   if(h5part_debug) fprintf(stderr,"SetStep to %d for file\n",step);
00536 #endif
00537   f->timestep=step;   /* because we start at 0 */
00538   if(f->timegroup>0) {
00539         H5Gclose(f->timegroup); 
00540   }
00541   f->timegroup=-1;
00542   sprintf(name,"Particles#%u",f->timestep);
00543   /*if(h5part_debug) fprintf(stderr,"P[%u] Open timegroup [%s] for file %d\n",
00544         f->myproc,name,f->file);*/
00545   if(f->mode==H5PART_READ) { /* kludge to prevent error messages */
00546 /*      if(h5part_debug) fprintf(stderr,"P[%u] open group\n"); */
00547     f->timegroup=H5Gopen(f->file,name);
00548   }
00549   if(f->timegroup<=0){
00550     /* timegroup doesn't exist, so we need to create one */
00551         /* if(h5part_debug) fprintf(stderr,"P[%u] create group\n"); */
00552     if(f->mode == H5PART_READ){
00553       fprintf(stderr,"Error in H5PartSetStep() Step #%d does not exist!\n",step);
00554     }
00555     f->timegroup = H5Gcreate(f->file,name,-1);
00556     if(f->timegroup<0) {
00557 #ifdef PARALLEL_IO
00558         fprintf(stderr,"p[%u] timegroup creation failed!\n",
00559                 f->myproc);
00560 #endif
00561         return;
00562     }
00563   }
00564   /*
00565     #ifdef PARALLEL_IO
00566     H5PartWriteStepAttrib(f,"pnparticles",H5T_NATIVE_INT64,f->pnparticles,f->nprocs);
00567     #endif
00568   */
00569 }
00570 
00571 /*
00572   H5PartIOcounter:  This is an entirely internal callback function 
00573    which is used in conjunction with HDF5 iterators.  The HDF5 Group
00574    iterator will call this repeatedly in order to count how many
00575    timesteps of data have been stored in a particular file.
00576    This is used by H5PartGetNumSteps().
00577 */
00578 herr_t H5PartIOcounter(hid_t group_id,
00579                    const char *member_name,
00580                    void *operator_data){
00581   int *count = (int*)operator_data;
00582   H5G_stat_t objinfo;
00583   /* only count the particle groups... ignore all others */
00584   if(!strncmp(member_name,"Particles",9)) (*count)++;
00585   return 0;
00586 }
00587 herr_t H5PartDScounter(hid_t group_id,
00588                    const char *member_name,
00589                    void *operator_data){
00590   int *count = (int*)operator_data;
00591   H5G_stat_t objinfo;
00592   /* only count the datasets... ignore all others */
00593   if(H5Gget_objinfo(group_id, 
00594                  member_name,
00595                  1 /* follow links */, 
00596                     &objinfo)<0) {
00597     return 0; /* error (probably bad symlink) */
00598   }
00599   if(objinfo.type==H5G_DATASET)    (*count)++;
00600   return 0;
00601 }
00602 
00603 typedef struct H5IO_getname_t {
00604   int index,count;
00605   char *name;
00606 }H5IO_getname_t;
00607 
00608 herr_t H5IOgetname(hid_t group_id,
00609                           const char *member_name, 
00610                           void *operator_data){
00611   H5IO_getname_t *getn = (H5IO_getname_t*)operator_data;
00612   /* check type first (only respond if it is a dataset) */
00613   H5G_stat_t objinfo;
00614   /* request info about the type of objects in root group */
00615   if(H5Gget_objinfo(group_id, 
00616                     member_name,
00617                     1 /* follow links */, 
00618                     &objinfo)<0) return 0; /* error (probably bad symlink) */
00619   /* only count objects that are datasets (not subgroups) */
00620   if(objinfo.type!=H5G_DATASET) 
00621     return 0; /* do not increment count if it isn't a dataset. */
00622   if(getn->index==getn->count){
00623     strcpy(getn->name,member_name);
00624     return 1; /* success */
00625   }
00626   getn->count++;
00627   return 0;
00628 }
00629 
00630 /* 
00631    H5PartGetNumSteps:  This reads the number of datasteps that are 
00632      currently stored in the datafile.  (simple return of an int).
00633      It works for both reading and writing of files, but is probably
00634      only typically used when you are reading.
00635 */
00636 int H5PartGetNumSteps(H5PartFile *f){
00637   /* iterate to get numsteps */
00638   int count=0;
00639   int idx=0;
00640   while(H5Giterate(f->file, /* hid_t loc_id, */
00641                    "/", /*const char *name, */
00642                    &idx, /* int *idx, */
00643                    H5PartIOcounter,
00644                    &count)<0){}
00645   return count;
00646 }
00647 int H5PartGetNumDatasets(H5PartFile *f){
00648   int count=0;
00649   int idx=0;
00650   char name[128];
00651   /* we need to have scanned file to get min timestep
00652      before we call this */
00653   sprintf(name,"Particles#%u",f->timestep);
00654   while(H5Giterate(f->file, /* hid_t loc_id */
00655                    name,
00656                    &idx,
00657                    H5PartDScounter,
00658                    &count)<0){}
00659   return count;   
00660 }
00661 int H5PartGetDatasetName(H5PartFile *f,
00662                          int _index, /* index of the dataset (0 to N-1) */
00663                          char *name, /* buffer to store name of dataset */
00664                          int maxlen){ /* max size of the "name" buffer */
00665   H5IO_getname_t getn;
00666   int idx=_index;
00667   char gname[128];
00668   sprintf(gname,"Particles#%u",f->timestep);
00669   getn.index=_index; getn.name=name; getn.count=_index;
00670   while(H5Giterate(f->file, /* hid_t loc_id, */
00671                    gname, /*const char *name, */
00672                    &idx, /* int *idx, */
00673                    H5IOgetname,
00674                    &getn)<0){}
00675   return 1;
00676 }
00677 
00678 hid_t H5PartGetDiskShape(H5PartFile *f,hid_t dataset){
00679   hid_t space = H5Dget_space(dataset);
00680   if(h5part_debug) fprintf(stderr,"H5PartGetDiskShape\n");
00681   if(H5PartHasView(f)){ 
00682     int r;
00683     hsize_t total,  stride, count;
00684     hssize_t range[2];
00685     if(h5part_debug) fprintf(stderr,"\tSelection is available\n");
00686     /* so, is this selection inclusive or exclusive? */
00687     range[0]=f->viewstart;
00688     range[1]=f->viewend;
00689     count = range[1]-range[0]; /* to be inclusive */
00690     stride=1;
00691     /* now we select a subset */
00692     if(f->diskshape>0)
00693       r=H5Sselect_hyperslab(f->diskshape,H5S_SELECT_SET,
00694                             range/* only using first element */,
00695                             &stride,&count,NULL);
00696     /* now we select a subset */
00697     r=H5Sselect_hyperslab(space,H5S_SELECT_SET,
00698                           range,&stride,&count,NULL);
00699     if(h5part_debug) fprintf(stderr,"\tSelection: range=%u:%u, npoints=%u s=%u\n",
00700             (int)range[0],(int)range[1],
00701             (int)H5Sget_simple_extent_npoints(space),
00702             (int)H5Sget_select_npoints(space));
00703     if(r<0){
00704       fprintf(stderr,"Abort: Selection Failed!\n");
00705       return space;
00706     }
00707   }
00708   else {
00709     if(h5part_debug) fprintf(stderr,"\tNo Selection\n");
00710   }
00711   return space;
00712 }
00713 
00714 hid_t H5PartGetMemShape(H5PartFile *f,hid_t dataset){  
00715   if(h5part_debug) fprintf(stderr,"H5PartGetMemShape\n");
00716   if(H5PartHasView(f)) {
00717     hsize_t dmax=H5S_UNLIMITED;
00718     hsize_t len = f->viewend - f->viewstart;
00719     return H5Screate_simple(1,&len,&dmax);
00720   }
00721   else {
00722     return H5S_ALL;
00723   }
00724 }
00725 /*
00726   H5PartGetNumParticles:  This gets the number of particles 
00727     that are stored in the current timestep.  It will arbitrarily
00728     select a timestep if you haven't already set the timestep
00729     with H5PartSetStep().
00730  */
00731 herr_t H5PartGetFirstDS(hid_t group_id,
00732                    const char *member_name,
00733                    void *operator_data){
00734   hid_t *dataset = (hid_t*)operator_data;
00735   H5G_stat_t objinfo;
00736   /* only count the particle groups... ignore all others */
00737   if(H5Gget_objinfo(group_id, 
00738                     member_name,
00739                     1 /* follow links */, 
00740                     &objinfo)<0) {
00741     return 0; /* error (probably bad symlink) */
00742   }
00743   if(objinfo.type==H5G_DATASET){
00744     (*dataset)=H5Dopen(group_id,member_name);
00745     return 1; /* all done: return success */
00746   }
00747   return 0; /* causes iterator to continue to next item */
00748 }
00749 
00750 long long H5PartGetNumParticles(H5PartFile *f){
00751   hid_t space,dataset;
00752   hsize_t nparticles;
00753   int idx=0;
00754   char name[128];
00755   /* we need to have scanned file to get min timestep
00756      before we call this */
00757   if(f->timegroup<0) {
00758     if(f->timestep<0)
00759       H5PartSetStep(f,0);
00760     else
00761       H5PartSetStep(f,f->timestep); /* choose a step */
00762   }
00763   if(f->timegroup<=0){
00764     fprintf(stderr,"Damnit!!! tried to select a timestep %d\n", f->timestep);
00765     exit(0);
00766   }
00767   /* lets open up a dataset in this group... we know "x" is there */
00768   /*  dataset=H5Dopen(f->timegroup,"x"); choice of X is a kludge of sorts */
00769   sprintf(name,"Particles#%u",f->timestep);
00770   while(H5Giterate(f->file, /* hid_t loc_id */
00771                    name,
00772                    &idx,
00773                    H5PartGetFirstDS,
00774                    &dataset)<0){}
00775   /*  space = H5Dget_space(dataset); */
00776   /* need to use H5PartGetDiskShape for any changes to f->diskshape */
00777   space = H5PartGetDiskShape(f,dataset); /* kludge (or utility depending on point of view) */
00778   if(H5PartHasView(f)){
00779     if(h5part_debug) fprintf(stderr,"\tGetNumParticles::get_selection\n");
00780     nparticles=H5Sget_select_npoints(space);
00781   }
00782   else {
00783     if(h5part_debug) fprintf(stderr,"\tGetNumParticles::get_simple_extent from space\n");
00784     nparticles= H5Sget_simple_extent_npoints(space);
00785   }
00786   if(space!=H5S_ALL) H5Sclose(space); /* release data shape handle */
00787   H5Dclose(dataset); /* release the dataset handle */
00788   return (long long)nparticles;
00789 }
00790 
00791 
00792 /*
00793   H5SetView: For parallel I/O or for subsetting operations on
00794   the datafile, the H5SetView subroutine allows you to define
00795   a subset of the total particle dataset to read.  The concept
00796   of "view" works for both serial and for parallel I/O.  The
00797   "view" will remain in effect until a new view is set, or the
00798   number of particles in a dataset changes, or the view is
00799     "unset" by calling H5SetView(file,-1,-1);
00800 
00801     Before you set a view, the H5PartGetNumParticles will
00802     return the total number of particles in a file (even for
00803     the parallel reads).  However, after you set a view, it
00804     will return the number of particles contained in the view.
00805 */
00806 void H5PartSetView(H5PartFile *f,long long start,long long end){
00807   hsize_t total,  stride, count;
00808   hssize_t range[2];
00809   int r;
00810   if(h5part_debug) fprintf(stderr,"SetView(%d,%d)\n",
00811           (int)start,(int)end);
00812   if(f->mode==H5PART_WRITE){
00813     fprintf(stderr,"H5PartSetView(): SetView does not make sense for write-only files.  It is meant to be used for read-only files. (maybe later this will change)\n");
00814     return;
00815   }
00816   /* if there is already a view selected, lets destroy it */ 
00817   f->viewstart=-1;
00818   f->viewend=-1;
00819   if(f->shape!=0){
00820     H5Sclose(f->shape);
00821     f->shape=0;
00822   }
00823   if(f->diskshape!=0 && f->diskshape!=H5S_ALL){
00824     H5Sclose(f->diskshape);
00825     f->diskshape=H5S_ALL;
00826   }
00827   f->diskshape = H5S_ALL;
00828   if(f->memshape!=0 && f->memshape!=H5S_ALL){
00829     H5Sclose(f->memshape);
00830     f->memshape=H5S_ALL;
00831   }
00832   if(start==-1 && end==-1) {
00833     if(h5part_debug) fprintf(stderr,"\tEarly Termination: Unsetting View\n");
00834     return; /* all done */
00835   }
00836   /* for now, we interpret start=-1 to mean 0 and 
00837      end==-1 to mean end of file */
00838   total=H5PartGetNumParticles(f);
00839   if(h5part_debug) fprintf(stderr,"\tTotal nparticles=%u\n",(int)total);
00840   if(start==-1) start=0;
00841   if(end==-1) end=total; /* can we trust nparticles (no)? 
00842                                                fortunately, view has been reset
00843                                               so H5PartGetNumParticles will tell
00844                                               us the total number of particles. */
00845 
00846   /* so, is this selection inclusive or exclusive? 
00847      it appears to be inclusive for both ends of the range.
00848   */
00849   if(end<start) {
00850         fprintf(stderr,"H5PartSetView(min=%d, max=%d):  Nonfatal error.  End of view is less than start.\n",
00851                 start,end);
00852         end=start; /* ensure that we don't have a range error */
00853   }
00854   range[0]=start;
00855   range[1]=end;
00856   /* setting up the new view */
00857   f->viewstart=range[0]; /* inclusive start */
00858   f->viewend=range[1]; /* inclusive end */
00859   f->nparticles=range[1]-range[0];
00860   if(h5part_debug) fprintf(stderr,"\tRange is now %u:%u\n",(int)range[0],(int)range[1]);
00861   /* OK, now we must create a selection from this */
00862 
00863   /* how to check shape... is default H5S_ALL? */
00864   f->shape = H5Screate_simple(1,&total,&total); /* declare overall datasize */
00865   /*  f->diskshape = H5S_ALL; */
00866   f->diskshape= H5Screate_simple(1,&total,&total); /* declare overall data size  but then will select a subset */
00867   {
00868     hsize_t dmax=H5S_UNLIMITED;
00869   f->memshape = H5Screate_simple(1,&(f->nparticles),&dmax); /* declare local memory datasize */
00870   }
00871   
00872   if(f->shape<0 || f->memshape<0 || f->diskshape<0){
00873     fprintf(stderr,"Abort: shape construction failed\n");
00874     if(f->shape<0) fprintf(stderr,"\tf->shape\n");
00875     if(f->diskshape<0) fprintf(stderr,"\tf->diskshape\n");
00876     if(f->memshape<0) fprintf(stderr,"\tf->memshape\n");
00877     exit(0);
00878   }
00879   if(h5part_debug) fprintf(stderr,"\tcount=%d\n",(int)total);
00880   stride=1;
00881   /* now we select a subset */
00882   r=H5Sselect_hyperslab(f->diskshape,H5S_SELECT_SET,range,&stride,&total,NULL);
00883   if(r<0){
00884     fprintf(stderr,"Abort: Selection Failed!\n");
00885     exit(0);
00886   }
00887      /* OK, now we have selected a reasonable hyperslab (all done) */
00888 }
00889 
00890 /*
00891   H5PartGetView: Allows you to query the current view. Start and End
00892   will be -1 if there is no current view established.
00893  */
00894 int H5PartGetView(H5PartFile *f,long long *start,long long *end){
00895   long long range[2];
00896   range[0]=(f->viewstart>=0)?f->viewstart:0;
00897   range[1]=(f->viewend>=0)?f->viewend:H5PartGetNumParticles(f);
00898   if(start) {
00899     *start=range[0];
00900   }
00901   if(end) {
00902     *end=range[1];
00903   }
00904   /* we could return the number of elements in the View as a convenience */
00905   return range[1]-range[0];
00906 }
00907 
00908 /* 
00909    H5SetCanonicalView: If it is too tedious to manually set the
00910    start and end coordinates for a view, the H5SetCanonicalView()
00911    will automatically select an appropriate domain decomposition of
00912    the data arrays for the degree of parallelism and set the "view" 
00913    accordingly.
00914 */
00915 void H5PartSetCanonicalView(H5PartFile *f){
00916   /* if a read_only file, search for on-disk canonical view */
00917   /* if this view does not exist, then if MPI, subdivide by numprocs */
00918   /* else, "unset" any existing View */
00919   if(f->mode != H5PART_READ){
00920     fprintf(stderr,"H5PartSetCanonicalView(): Views do not make sense for write-only files.  It is meant to be used for read-only files. (maybe later this will change)\n");
00921     return;
00922   }
00923   H5PartSetView(f,-1,-1); /* unset the view */
00924 #ifdef PARALLEL_IO
00925   if(f->timegroup<0){
00926     H5PartSetStep(f,0); /* set to first step in file */
00927   }
00928   /* 
00929      now lets query the attributes for this group to see if there is
00930      a 'pnparticles' group that contains the offsets for the processors.
00931   */
00932   
00933   if(H5PartReadStepAttrib(f,"pnparticles",f->pnparticles)<0){ /* try to read pnparticles right off of the disk */
00934     /* automatically subdivide the view into NP mostly equal pieces */
00935     int i;
00936     long long total=0, n = H5PartGetNumParticles(f);
00937     n/=f->nprocs;
00938     f->pnparticles[0]=n;
00939     total=n;
00940     for(i=1;i<f->nprocs;i++){
00941       f->pnparticles[i]=n;
00942       total+=n;
00943     }
00944   }
00945   {
00946     int i;
00947     long long total = 0, n = H5PartGetNumParticles(f);
00948     /* now we set the view for this processor */
00949     for(i=0;i<f->myproc;i++){
00950       total+=f->pnparticles[i];
00951     }
00952     H5PartSetView(f,total,total+f->pnparticles[f->myproc]-1);
00953   }
00954 #endif
00955   /* the canonical view is to see everything if this is serial
00956      so there is nothing left to do */
00957 }
00958 
00959 /*
00960   H5PartReadArray:  This reads in an individual array from a
00961     particlar timestep.  Unlike its "Write" mode sibling, this routine
00962     is completely public and will not have any wacky state dependencies.
00963     If you haven't selected a particular timestep, it will pick
00964     the current one.
00965 */
00966 int H5PartReadDataFloat64(H5PartFile *f,char *name,double *array){
00967   hid_t space,memspace,dataset,datatype;
00968   if(!f->timegroup) H5PartSetStep(f,f->timestep); /* choose current step */
00969   dataset=H5Dopen(f->timegroup,name);
00970   space = H5PartGetDiskShape(f,dataset); /* gets space with selection if view is set */
00971   memspace = H5PartGetMemShape(f,dataset);
00972   /*  datatype=H5Dget_type(dataset); */
00973   H5Dread(dataset, /* handle for the dataset */
00974           H5T_NATIVE_DOUBLE, /* the datatype we use in memory 
00975                               you can change it to FLOAT if you want */
00976           memspace, /* shape/size of data in memory (the complement to disk hyperslab) */
00977           space, /* shape/size of data on disk  (get hyperslab if needed) */
00978           H5P_DEFAULT,/* ignore... its for parallel reads */
00979           array); /* the data array we are reading into */
00980   if(space!=H5S_ALL) H5Sclose(space); /* release data shape handle */
00981   if(memspace!=H5S_ALL) H5Sclose(memspace);
00982   H5Dclose(dataset); /* release the dataset handle */
00983   return 1;
00984 }
00985 
00986 int H5PartReadDataInt64(H5PartFile *f,char *name,long long *array){
00987   hid_t space,memspace,dataset,datatype;
00988   if(!f->timegroup) H5PartSetStep(f,f->timestep); /* choose a step */
00989   dataset=H5Dopen(f->timegroup,name);
00990   space = H5PartGetDiskShape(f,dataset); /* H5Dget_space(dataset); */
00991   memspace = H5PartGetMemShape(f,dataset);
00992   /*  datatype=H5Dget_type(dataset); */
00993   H5Dread(dataset, /* handle for the dataset */
00994           H5T_NATIVE_INT64, /* the datatype we use in memory 
00995                               you can change it to FLOAT if you want */
00996           memspace, /* shape/size of data in memory (complement to disk hyperslab) */
00997           space, /* shape/size of data on disk  (currently get all) */
00998           H5P_DEFAULT,/* ignore... its for parallel reads */
00999           array); /* the data array we are reading into */
01000   if(space!=H5S_ALL) H5Sclose(space); /* release data shape handle */
01001   if(memspace!=H5S_ALL) H5Sclose(memspace);
01002   H5Dclose(dataset); /* release the dataset handle */
01003   return 1; /* totally bogus */
01004 }
01005 
01006 /*
01007   H5PartReadParticleStep:  This is the mongo read function that
01008     pulls in all of the data for a given timestep in one shot.
01009     It also takes the timestep as an argument and will call
01010     H5PartSetStep() internally so that you don't have to 
01011     make that call separately.
01012     See also: H5PartReadArray() if you want to just
01013     read in one of the many arrays.
01014 */
01015 int H5PartReadParticleStep(H5PartFile *f,
01016                            int step,
01017                            double *x,double *y,double *z,
01018                            double *px,double *py,double *pz,
01019                            long long *id){
01020   H5PartSetStep(f,step);
01021   /* or smuggle it into the array names */
01022   H5PartReadDataFloat64(f,"x",x);
01023   H5PartReadDataFloat64(f,"y",y);
01024   H5PartReadDataFloat64(f,"z",z);
01025   H5PartReadDataFloat64(f,"px",px);
01026   H5PartReadDataFloat64(f,"py",py);
01027   H5PartReadDataFloat64(f,"pz",pz);
01028   H5PartReadDataInt64(f,"id",id);
01029   return 1;
01030 }
01031 
01032 /**************** File Stashing Interfaces *************************/
01033 
01034 herr_t H5NameExists(hid_t group_id,
01035                    const char *member_name,
01036                      void *v){
01037   if(!strcmp(member_name,(char*)v)) return 1;
01038   else return 0;
01039 }
01040 
01041 int H5PartFileHasName(H5PartFile *f,
01042                       char *dir,char *name){
01043   if(H5Giterate(f->file, /* hid_t loc_id, */
01044                 dir, /*const char *name, */
01045                 NULL, /* int *idx, */
01046                 H5NameExists,
01047                 (void*)name)<0)
01048     return 1;
01049   else
01050     return 0;
01051 }
01052 
01053 int H5PartStashFile(H5PartFile *f,char *filename){
01054   hid_t udata=0,files=0,rgroup=0;
01055   FILE *file;
01056   int returnvalue=0;
01057   
01058   rgroup = H5Gopen(f->file,"/");
01059   if(H5PartFileHasName(f,"/","UserData")){
01060     udata = H5Gopen(rgroup,"UserData");
01061     if(H5PartFileHasName(f,"UserData","Files")){
01062       files=H5Gopen(udata,"Files");
01063     }
01064     else {
01065       files = H5Gcreate(udata,"Files",-1);
01066     }
01067   }
01068   else {
01069     /* must create the UserData group */
01070     udata = H5Gcreate(rgroup,"UserData",-1);
01071     files = H5Gcreate(udata,"Files",-1);
01072   }
01073   if(rgroup) H5Gclose(rgroup); rgroup=0;
01074   if(udata) H5Gclose(udata); udata=0;
01075   /* now we stash the file into the files subdir */
01076   /* first make sure there isn't a file with the same
01077      name already there? */
01078   file = fopen(filename,"r");
01079   if(file){
01080     hsize_t sz;
01081     char *buffer,*dsname,*dsbuffer;
01082     hid_t fspace,fdata;
01083     fseek(file,0,SEEK_END);
01084     sz = ftell(file);
01085     buffer=(char*)malloc(sz);
01086     fspace=H5Screate_simple(1,&sz,0);
01087     /* need to strip off the /'s from the filename before creating dataset */
01088     dsbuffer = (char*)malloc(strlen(filename));
01089     strcpy(dsbuffer,filename);
01090     dsname = strrchr(dsbuffer,'/');
01091     if(!dsname) dsname=dsbuffer;
01092     fdata=H5Dcreate(files,dsname,H5T_NATIVE_CHAR,fspace,H5P_DEFAULT);
01093     H5Dwrite(fdata,H5T_NATIVE_CHAR,H5S_ALL,H5S_ALL,H5P_DEFAULT,buffer);
01094     H5Dclose(fdata);
01095     H5Sclose(fspace);
01096     fclose(file);
01097     free(buffer); free(dsbuffer);
01098     returnvalue = 1; /* success */
01099   }
01100   H5Gclose(files);
01101   return returnvalue;
01102 }
01103 
01104 int H5PartUnstashFile(H5PartFile *f,char *filename, char *outputpath){
01105   if(H5PartFileHasName(f,"/","UserData") && 
01106      H5PartFileHasName(f,"/UserData","Files") && 
01107      H5PartFileHasName(f,"/UserData/Files",filename)){
01108     /* extract the datafile from the HDF5 file */
01109     hid_t fdata,fspace,fgroup;
01110     hsize_t sz;
01111     char *buffer,*outname;
01112     FILE *file;
01113     fgroup = H5Gopen(f->file,"/UserData/Files");
01114     fdata = H5Dopen(fgroup,filename);
01115     fspace = H5Dget_space(fdata);
01116     sz = H5Sget_simple_extent_npoints(fspace);
01117     buffer = (char*)malloc(sz);
01118     H5Dread(fdata,H5T_NATIVE_CHAR,H5S_ALL,H5S_ALL,H5P_DEFAULT,buffer);
01119     outname = (char*)malloc(strlen(filename) + 8 + outputpath?strlen(outputpath):0);
01120     if(outputpath && strlen(outputpath)>0){
01121       if(outputpath[strlen(outputpath)-1]!='/') sprintf(outname,"%s/%s",outputpath,filename);
01122       else sprintf(outname,"%s%s",outputpath,filename);
01123     }
01124     else {
01125       strcpy(outname,filename);
01126     }
01127     file = fopen(outname,"w");
01128     fwrite(buffer,1,sz,file);
01129     fclose(file);
01130     free(buffer);
01131     free(outname);
01132     H5Sclose(fspace);
01133     H5Dclose(fdata);
01134     H5Gclose(fgroup);
01135     return 1;
01136   }
01137   return 0;
01138 }
01139 
01140 int H5PartGetNumStashFiles(H5PartFile *f){
01141   hsize_t retval;
01142   if(H5PartFileHasName(f,"/","UserData") && 
01143      H5PartFileHasName(f,"/UserData","Files")){
01144     hid_t fgroup;
01145     /* we will use an iterator for this to count stash files */
01146     fgroup = H5Gopen(f->file,"/UserData/Files");
01147     H5Gget_num_objs(fgroup,&retval);
01148     return retval;
01149   }
01150   else return 0;
01151 }
01152 
01153 int H5PartFileGetStashFileName(H5PartFile *f,int nameindex,char *filename,int maxnamelen){
01154   return 1;
01155 }

Generated on Mon Jan 16 13:23:48 2006 for IPPL by  doxygen 1.4.6