コード例 #1
0
ファイル: datCopy.c プロジェクト: Starlink/hds-v5
int
datCopy( const HDSLoc *locator1, const HDSLoc *locator2,
         const char *name_str, int *status) {

  char sourcename[DAT__SZNAM+1];
  char cleanname[DAT__SZNAM+1];
  hid_t parent_id = -1;
  hid_t objid = -1;

  if (*status != SAI__OK) return *status;

  /* Validate input locators. */
  dat1ValidateLocator( "datCopy", 1, locator1, 1, status );
  dat1ValidateLocator( "datCopy", 1, locator2, 0, status );

  dau1CheckName( name_str, 1, cleanname, sizeof(cleanname), status );
  if (*status != SAI__OK) return *status;

  /* Have to give the source name as "." doesn't seem to be allowed.
     so get the name and the parent locator. */
  objid = dat1RetrieveIdentifier( locator1, status );

  /* If we are at the root group we can not get a parent so just use
     the "/" name instead */
  parent_id = dat1GetParentID( objid, 1, status );
  if (*status == DAT__OBJIN) {
    emsAnnul(status);
    star_strlcpy( sourcename, "/", sizeof(sourcename));
    parent_id = -1;
  } else {
    datName( locator1, sourcename, status );
  }
  CALLHDFQ(H5Ocopy( (parent_id == -1 ? objid : parent_id), sourcename,
                    locator2->group_id, cleanname, H5P_DEFAULT, H5P_DEFAULT));

 CLEANUP:
  if (parent_id) H5Gclose(parent_id);
  return *status;

}
コード例 #2
0
ファイル: errClear_adam.c プロジェクト: astrobuff/starlink
void errClear( int * status ) {
  int level;      /* Error context level */
  int tstlev = 0; /* Test level variable */

  /*  Initialise the error context level. */
  emsLevel( &level );

  /*  Loop to return the Error Reporting System to the default context
   *  level. We assume we're there when emsRlse will go no lower. */
  while ( level != tstlev) {
    tstlev = level;
    emsRlse();
    emsLevel( &level );
  }

  /*  Check if there are any error messages pending output in the error
   *  table. */
  emsStat( status );
  if (*status != SAI__OK) {

    /*     There are error messages pending output, so call ERR_FLUSH to
     *     deliver them to the user. */
    errFlush( status );

    /*     Check the returned status for output errors: if they have
     *     occurred, annul the error table at the current (default) context. */
    if (*status != SAI__OK) emsAnnul( status );

  } else {

    /*     There are no pending error messages, so just reset the status to
     *     SAI__OK. (the if statement guarantees this but it was done this
     *     way in Fortran) */
    *status = SAI__OK;
  }
}
コード例 #3
0
ファイル: datMap.c プロジェクト: Starlink/hds-v5
int
datMap(HDSLoc *locator, const char *type_str, const char *mode_str, int ndim,
       const hdsdim dims[], void **pntr, int *status) {

  int isprim = 0;
  char normtypestr[DAT__SZTYP+1];
  size_t nbytes = 0;
  hid_t h5type = 0;
  int isreg = 0;
  void *regpntr = NULL;
  void *mapped = NULL;
  hdsmode_t accmode = HDSMODE_UNKNOWN;
  haddr_t offset;
  hdsbool_t try_mmap = HDS_FALSE;
  unsigned intent = 0;
  size_t actbytes = 0;

  if (*status != SAI__OK) return *status;

  /* First have to validate the access mode */
  switch (mode_str[0]) {
  case 'R':
  case 'r':
    accmode = HDSMODE_READ;
    break;
  case 'U':
  case 'u':
    accmode = HDSMODE_UPDATE;
    break;
  case 'W':
  case 'w':
    accmode = HDSMODE_WRITE;
    break;
  default:
    *status = DAT__MODIN;
    emsRepf("datMap_6", "Unrecognized mode string '%s' for datMap",
            status, mode_str);
    goto CLEANUP;
  }

  /* Validate input locator. */
  dat1ValidateLocator( "datMap", 1, locator, (accmode & HDSMODE_READ), status );

  /* Get the HDF5 type code and confirm this is a primitive type */
  isprim = dau1CheckType( 1, type_str, &h5type, normtypestr,
                          sizeof(normtypestr), status );

  if (!isprim) {
    if (*status == SAI__OK) {
      *status = DAT__TYPIN;
      emsRepf("datMap_1", "datGet: Data type must be a primitive type and not '%s'",
              status, normtypestr);
    }
    goto CLEANUP;
  }

  /* Not allowed to map undefined data in READ or UPDATE mode */
  if (accmode == HDSMODE_UPDATE || accmode == HDSMODE_READ) {
    hdsbool_t defined;
    if (*status == SAI__OK) {
      datState( locator, &defined, status );
      if (!defined) {
        *status = DAT__UNSET;
        emsRepf("datMap_6bb", "Can not map an undefined primitive in mode '%s'",
                status, mode_str);
        goto CLEANUP;
      }
    }
  }

  /* How did we open this file? */
  CALLHDFQ( H5Fget_intent( locator->file_id, &intent ));
  if (accmode == HDSMODE_UPDATE || accmode == HDSMODE_WRITE) {
    /* Must check whether the file was opened for write */
    if ( intent == H5F_ACC_RDONLY ) {
      *status = DAT__ACCON;
      emsRepf("datMap_6b", "datMap: Can not map readonly locator in mode '%s'",
             status, mode_str);
      goto CLEANUP;
    }
  }

  /* Verify that the specified dimensions match the locator dimensions */
  if (*status == SAI__OK) {
    hdsdim locdims[DAT__MXDIM];
    int locndims;
    int i;
    datShape(locator, DAT__MXDIM, locdims, &locndims, status );

    /* Note that if we are mapping as a scalar the locator should
       refer to a single element */
    if (ndim == 0) {
      size_t nelem = 1;
      for (i=0; i<locndims; i++) {
        nelem *= locdims[i];
      }
      if (nelem != 1) {
        *status = DAT__DIMIN;
        emsRepf("datMap_6e", "datMap: Attempt to map as a scalar but locator"
                " refers to a primitive with %zu elements",
                status, nelem);
        goto CLEANUP;
      }
    } else {
      if (ndim != locndims) {
        *status = DAT__DIMIN;
        emsRepf("datMap_6c", "datMap: Dimensionality mismatch --"
                " requested number: %d locator number: %d", status,
                ndim, locndims );
        goto CLEANUP;
      }
      for (i=0; i<ndim; i++) {
        if ( locdims[i] != dims[i] ) {
          *status = DAT__DIMIN;
          emsRepf("datMap_6d", "datMap: Dimension %d has size %zu but requested size %zu",
                  status, i, (size_t)locdims[i], (size_t)dims[i]);
          goto CLEANUP;
        }
      }
    }
  }

  /* There is a super-special case for datMap when called with a map
     type of "_CHAR". In that case we need to work out the size ourselves
     and adjust the type size */
  if (strcmp( "_CHAR", normtypestr ) == 0 ) {
    size_t clen = 0;
    char tmpbuff[DAT__SZTYP+1];
    datClen( locator, &clen, status );
    CALLHDFQ( H5Tset_size( h5type, clen ) );
    one_snprintf( tmpbuff, sizeof(tmpbuff), "*%zu",
                  status, clen );
    one_strlcat( normtypestr, tmpbuff, DAT__SZTYP+1, status );
  }

  /* Now we want the HDSTYPE of the requested type so that we can work out how much
     memory we will need to allocate. */
  CALLHDFE( size_t, nbytes,
          H5Tget_size( h5type ),
          DAT__HDF5E,
          emsRep("datLen_size", "datMap: Error obtaining size of requested data type",
                 status)
          );

  {
    int i;
    if (ndim > 0) {
      for (i = 0; i < ndim; i++) {
        nbytes *= dims[i];
      }
    }
  }


  /* Work out whether memory mapping is possible -- at the moment
     I'm pretty sure the only safe use of mmap is when we are reading
     the data and the file itself was opened readonly. I'm not sure what happens
     if other components are removed or added -- will the offset change? Maybe we just try */
  offset = H5Dget_offset( locator->dataset_id );
  if (offset != HADDR_UNDEF) {
    hid_t dataset_h5type = 0;
    /* In theory we can do a memory map so now compare
       the data types of the request and the low-level dataset. */
    CALLHDFE( hid_t, dataset_h5type,
             H5Dget_type( locator->dataset_id ),
             DAT__HDF5E,
             emsRep("datMap_type", "datType: Error obtaining data type of dataset", status)
             );
    if (H5Tequal( dataset_h5type, h5type )) {
      try_mmap = HDS_TRUE;
    }
    H5Tclose(dataset_h5type);
  }

  /* If this is a locator to a slice then for now we can't memory map. In theory
     if we knew the slice was contiguous (e.g a vectorized slice, or a single
     plane of a cube then we could mmap it anyhow. We do not want to have to
     emulate HDF5 dataspaces here */
  if (locator->isslice) try_mmap = 0;

  /* There seem to be issues doing this on files opened for update/write.
     For now only allow mmap for files opened read only */
  if (intent != H5F_ACC_RDONLY) try_mmap = 0;

  /* If mmap has been disabled by tuning the environment we just force it off here. */
  if (!hds1GetUseMmap()) try_mmap = 0;

#if DEBUG_HDS
  {
    char *name_str;
    char * file_str;
    const char * reason;
    name_str = dat1GetFullName( locator->dataset_id, 0, NULL, status );
    file_str = dat1GetFullName( locator->dataset_id, 1, NULL, status );
    if (offset != HADDR_UNDEF) {
      reason = "[HAD offset]";
    } else {
      reason = "[no offset]";
    }
    if (!try_mmap) {
      printf("Will NOT attempt %s to mmap %s:%s\n",reason,file_str,name_str);
    } else {
      printf("WILL TRY %s to mmap OFFSET=%zu %s:%s\n", reason, (size_t)offset, file_str, name_str);
    }
    MEM_FREE(name_str);
  }
#endif

  if (try_mmap) {
    int fd = 0;
    int flags = 0;
    int prot = 0;
    hdsbool_t opened_fd = 0;

    if ( intent == H5F_ACC_RDONLY || accmode == HDSMODE_READ ) {
      flags |= O_RDONLY;
      prot = PROT_READ;
    } else {
      flags |= O_RDWR;
      prot = PROT_READ | PROT_WRITE;
    }

    if (*status == SAI__OK) {
      /* see what file driver we have */
      hid_t fapl_id = -1;
      hid_t fdriv_id = -1;
      void * file_handle = NULL;
      herr_t herr = -1;
      fapl_id = H5Fget_access_plist(locator->file_id);
      fdriv_id = H5Pget_driver(fapl_id);
      if (fdriv_id == H5FD_SEC2 || fdriv_id == H5FD_STDIO) {
        /* If this is a POSIX or STDIO driver we get the handle */
        herr = H5Fget_vfd_handle( locator->file_id, fapl_id, (void**)&file_handle);
        if (herr >= 0) {
          if (fdriv_id == H5FD_SEC2) {
            fd = *((int *)file_handle);
          } else if (fdriv_id == H5FD_STDIO) {
            FILE * fh = (FILE *)file_handle;
            fd = fileno(fh);
          }
        }
      }
      if (fapl_id > 0) H5Pclose( fapl_id );

      if (fd == 0) {
        /* We have to open the file ourselves! */
        char * fname = NULL;
        fname = dat1GetFullName( locator->dataset_id, 1, NULL, status );
        fd = open(fname, flags);
        opened_fd = 1;
        if (fname) MEM_FREE(fname);
      }
      if (fd > 0) {
        /* Set up for memory mapping */
        int mflags = 0;
        mflags = MAP_SHARED | MAP_FILE;
        if (*status == SAI__OK) {
          mapped = dat1Mmap( nbytes, prot, mflags, fd, offset, &isreg, &regpntr, &actbytes, status );
          if (*status == SAI__OK) {
            /* Store the file descriptor in the locator to allow us to close */
            if (mapped) {
              if (opened_fd) locator->fdmap = fd;
              locator->uses_true_mmap = 1;
            }
          } else {
            /* Not currently fatal -- we can try without the file */
            if (opened_fd) close(fd);
            emsAnnul(status);
          }
        }
      }
    }
  }

  /* If we have not been able to map anything yet, just get some memory. It is
     zeroed (for WRITE) to match mmap behavior. We rely on the OS to decide when it is reasonable
     to do an anonymous mmap. */

  if (!regpntr) {
    hdsbool_t mustget;
    mustget = (accmode == HDSMODE_READ || accmode == HDSMODE_UPDATE);

    if (mustget) {
      regpntr = cnfMalloc( nbytes );
    } else {
      regpntr = cnfCalloc( 1, nbytes );
    }
    if (!regpntr) {
      *status = DAT__NOMEM;
      emsRepf("datMap_cnf","datMap: Unable to allocate %zu bytes of memory",
              status, nbytes);
      goto CLEANUP;
    }

    /* Populate the memory - check with datState occurred earlier */
    if (mustget) {
      datGet( locator, normtypestr, ndim, dims, regpntr, status );
    }
  }

 CLEANUP:
  /* Cleanups that must happen always */
  if (h5type) H5Tclose(h5type);

  /* cleanups that only happen if status is bad */
  if (*status != SAI__OK) {
    if (mapped) {
      if (isreg == 1) cnfUregp( regpntr );
      if ( munmap( mapped, actbytes ) != 0 ) {
        emsSyser( "MESSAGE", errno );
        emsRep("datMap_4", "Error unmapping mapped memory: ^MESSAGE", status);
      }
      mapped = NULL;
    } else if (regpntr) {
      cnfFree( regpntr );
    }
    regpntr = NULL;
  }

  /* Update the locator to reflect the mapped status */
  if (*status == SAI__OK) {
    int i;
    locator->pntr = mapped;
    locator->regpntr = regpntr;
    locator->bytesmapped = actbytes;
    locator->accmode = accmode;

    /* In order to copy the data back into the underlying HDF5 dataset
       we need to store additional information about how this was mapped
       to allow us to either call datPut later on or at least a new
       dataspace. For now store the arguments so we can pass them straight
       to datPut */
    locator->ndims = ndim;
    for (i=0; i<ndim; i++) {
      (locator->mapdims)[i] = dims[i];
    }
    star_strlcpy( locator->maptype, normtypestr, sizeof(locator->maptype) );
  }

  /* Note that the returned pointer is not necessarily the same as the
     mapped pointer because of pagesize corrections */
  *pntr = regpntr;

  return *status;
}
コード例 #4
0
ファイル: datMsg.c プロジェクト: astrobuff/starlink
void datMsg( const char * token, const HDSLoc * loc ) {

  /*  Local Variables: */
  char buff[EMS__SZMSG+EMS__SZMSG+2];  /* Buffer for file+path */
  char file[EMS__SZMSG+1];             /* Container file name */
  char path[EMS__SZMSG+1];             /* Object path name */

  char *bra;   /* Position of '(' character */
  char *dot;   /* Position of '.' */
  size_t ncf;   /* Number of characters in filename */
  int nlev; /* Object level in HDS */
#if defined( vms )
  char *semi;  /* Position of ';' */
#endif
  char *start; /* Position to start in path name */
  int status = DAT__OK; /* local status variable */
  int odd;   /* Is the filename odd? */
  int ok;    /* No error occurred? */

  /*  Mark the error stack */
  emsMark();

  /*  Obtain the data object path and container file name. */
  hdsTrace( loc, &nlev, path, file, &status, sizeof(path), sizeof(file) );

  if ( status == DAT__OK ) {

    /*  If necessary, handle VAX/VMS file names.  Locate the semicolon which
     *  delimits the version number in the file name. */

#if defined( vms )

    semi = strchr( file, ';' );

    /*  If found, then select the file name prior to it by replacing
	it with a nul. */
    if (semi != NULL ) {
      *semi = '\0';
    }

#endif

    /* Find the filename length */
    ncf = strlen( file );

    /*  See if the file is "odd". Check to see if it has the default file
     *  extension of '.SDF' with at least one character preceding it. */

    odd = 1;
    if ( ncf >= 5 ) {
      if ( strcmp( &file[ncf-DAT__SZFLX], DAT__FLEXT ) == 0) {
	odd = 0;
      } else {
	odd = 1;
      }
    }

    /*  If the file name is not odd, then omit the file extension. */
    if (!odd) file[ncf-DAT__SZFLX] = '\0';

    /*  Enter the file name into the buffer, surrounding it in quotes if it
     *  is odd. */

    *buff = '\0';
    if (odd) strcat(buff, "\"" );
    strcat( buff, file );
    if (odd) strcat(buff, "\"" );

    /*  If the object is not a top-level object, then find the position of
     *  the first '.' in its pathname, which marks the start of the first
     *  component name. */

    if (nlev > 1 ) {

      dot = strchr( path, '.' );

      /*  If successful, see if the '.' is preceded by a '(' indicating that
       *  the top-level object is subscripted. Derive the starting position in
       *  the path name so that the subscript is used if present. */

      if (dot != NULL) {

	bra = strchr( path, '(' );
	if (bra != NULL && bra < dot) {
	  start = bra;
	} else {
	  start = dot;
	}

	/*  Add the required part of the path name to the buffer. */
	strcat( buff, start );

      }

    } else {
      /*  If the object is a top-level object, then see if it is subscripted.
       *  If so, then add the subscript to the buffer. */

      start = strchr( path, '(' );

      if ( start != NULL ) {
	strcat( buff, start );
      }

    }

  }

  /*  Note if any error has occurred. */
  ok = ( status == DAT__OK  ? 1 : 0 );

  /*  If an error occurred, then annul it. Release the error stack. */
  if ( status != DAT__OK ) emsAnnul( &status );
  emsRlse();

  /*  If no error occurred, then assign the resulting buffer contents to
   *  the message token. */
  if (ok) emsSetc( token, buff );

}