netCDF  4.2.1.1
 All Data Structures Files Functions Variables Typedefs Macros Groups Pages
dfile.c
Go to the documentation of this file.
1 
11 #include "config.h"
12 #include <stdlib.h>
13 #ifdef HAVE_SYS_RESOURCE_H
14 #include <sys/resource.h>
15 #endif
16 #ifdef HAVE_SYS_TYPES_H
17 #include <sys/types.h>
18 #endif
19 #ifdef HAVE_SYS_STAT_H
20 #include <sys/stat.h>
21 #endif
22 #ifdef HAVE_FCNTL_H
23 #include <fcntl.h>
24 #endif
25 #include "ncdispatch.h"
26 
27 static int nc_initialized = 0;
28 
66 size_t* NC_coord_zero;
67 size_t* NC_coord_one;
68 
69 static void
70 nc_local_initialize(void)
71 {
72  int i;
73  NC_coord_zero = (size_t*)malloc(sizeof(size_t)*NC_MAX_VAR_DIMS);
74  if(NC_coord_zero == NULL) abort();
75  NC_coord_one = (size_t*)malloc(sizeof(size_t)*NC_MAX_VAR_DIMS);
76  if(NC_coord_one == NULL) abort();
77  for(i=0;i<NC_MAX_VAR_DIMS;i++) {
78  NC_coord_one[i] = 1;
79  NC_coord_zero[i] = 0;
80  }
81 }
82 
83 static int
84 NC_check_file_type(const char *path, int use_parallel, void *mpi_info,
85  int *cdf, int *hdf)
86 {
87  char magic[MAGIC_NUMBER_LEN];
88 
89  *hdf = 0; *cdf = 0;
90 
91  /* Get the 4-byte magic from the beginning of the file. Don't use posix
92  * for parallel, use the MPI functions instead. */
93 #ifdef USE_PARALLEL_MPIO
94  if (use_parallel)
95  {
96  MPI_File fh;
97  MPI_Status status;
98  int retval;
99  MPI_Comm comm = 0;
100  MPI_Info info = 0;
101 
102  if(mpi_info != NULL) {
103  comm = ((NC_MPI_INFO*)mpi_info)->comm;
104  info = ((NC_MPI_INFO*)mpi_info)->info;
105  }
106  if((retval = MPI_File_open(comm, (char *)path, MPI_MODE_RDONLY,info,
107  &fh)) != MPI_SUCCESS)
108  return NC_EPARINIT;
109  if((retval = MPI_File_read(fh, magic, MAGIC_NUMBER_LEN, MPI_CHAR,
110  &status)) != MPI_SUCCESS)
111  return NC_EPARINIT;
112  if((retval = MPI_File_close(&fh)) != MPI_SUCCESS)
113  return NC_EPARINIT;
114  } else
115 #endif /* USE_PARALLEL */
116  {
117  FILE *fp;
118  int i;
119 
120  if(path == NULL || strlen(path)==0)
121  return NC_EINVAL;
122 
123  if (!(fp = fopen(path, "r")))
124  return errno;
125  i = fread(magic, MAGIC_NUMBER_LEN, 1, fp);
126  fclose(fp);
127  if(i != 1)
128  return errno;
129  }
130 
131  /* Ignore the first byte for HDF */
132  if(magic[1] == 'H' && magic[2] == 'D' && magic[3] == 'F')
133  *hdf = 5;
134  else if(magic[0] == '\016' && magic[1] == '\003'
135  && magic[2] == '\023' && magic[3] == '\001')
136  *hdf = 4;
137  else if(magic[0] == 'C' && magic[1] == 'D' && magic[2] == 'F')
138  {
139  if(magic[3] == '\001')
140  *cdf = 1; /* netcdf classic version 1 */
141  else if(magic[3] == '\002')
142  *cdf = 2; /* netcdf classic version 2 */
143  }
144 
145  return NC_NOERR;
146 }
147 
344 int
345 nc_create(const char *path, int cmode, int *ncidp)
346 {
347  return nc__create(path,cmode,NC_SIZEHINT_DEFAULT,NULL,ncidp);
348 }
349 
411 int
412 nc__create(const char *path, int cmode, size_t initialsz,
413  size_t *chunksizehintp, int *ncidp)
414 {
415  return NC_create(path, cmode, initialsz, 0,
416  chunksizehintp, 0, NULL, ncidp);
417 
418 }
427 int
428 nc__create_mp(const char *path, int cmode, size_t initialsz,
429  int basepe, size_t *chunksizehintp, int *ncidp)
430 {
431  return NC_create(path, cmode, initialsz, basepe,
432  chunksizehintp, 0, NULL, ncidp);
433 }
434 
546 int
547 nc_open(const char *path, int mode, int *ncidp)
548 {
549  return NC_open(path, mode, 0, NULL, 0, NULL, ncidp);
550 }
551 
603 int
604 nc__open(const char *path, int mode,
605  size_t *chunksizehintp, int *ncidp)
606 {
607  return NC_open(path, mode, 0, chunksizehintp, 0,
608  NULL, ncidp);
609 }
610 
619 int
620 nc__open_mp(const char *path, int mode, int basepe,
621  size_t *chunksizehintp, int *ncidp)
622 {
623  return NC_open(path, mode, basepe, chunksizehintp,
624  0, NULL, ncidp);
625 }
626 
644 int
645 nc_inq_path(int ncid, size_t *pathlen, char *path)
646 {
647  NC* ncp;
648  int stat = NC_NOERR;
649  if ((stat = NC_check_id(ncid, &ncp)))
650  return stat;
651  if(ncp->path == NULL) {
652  if(pathlen) *pathlen = 0;
653  if(path) path[0] = '\0';
654  } else {
655  if (pathlen) *pathlen = strlen(ncp->path);
656  if (path) strcpy(path, ncp->path);
657  }
658  return stat;
659 }
660 
709 int
710 nc_redef(int ncid)
711 {
712  NC* ncp;
713  int stat = NC_check_id(ncid, &ncp);
714  if(stat != NC_NOERR) return stat;
715  return ncp->dispatch->redef(ncid);
716 }
717 
773 int
774 nc_enddef(int ncid)
775 {
776  int status = NC_NOERR;
777  NC *ncp;
778  status = NC_check_id(ncid, &ncp);
779  if(status != NC_NOERR) return status;
780  return ncp->dispatch->_enddef(ncid,0,1,0,1);
781 }
782 
864 int
865 nc__enddef(int ncid, size_t h_minfree, size_t v_align, size_t v_minfree,
866  size_t r_align)
867 {
868  NC* ncp;
869  int stat = NC_check_id(ncid, &ncp);
870  if(stat != NC_NOERR) return stat;
871  return ncp->dispatch->_enddef(ncid,h_minfree,v_align,v_minfree,r_align);
872 }
873 
941 int
942 nc_sync(int ncid)
943 {
944  NC* ncp;
945  int stat = NC_check_id(ncid, &ncp);
946  if(stat != NC_NOERR) return stat;
947  return ncp->dispatch->sync(ncid);
948 }
949 
992 int
993 nc_abort(int ncid)
994 {
995  NC* ncp;
996  int stat = NC_check_id(ncid, &ncp);
997  if(stat != NC_NOERR) return stat;
998  if(ncp->path != NULL) free(ncp->path);
999  ncp->path = NULL;
1000  return ncp->dispatch->abort(ncid);
1001 }
1002 
1043 int
1044 nc_close(int ncid)
1045 {
1046  NC* ncp;
1047  int stat = NC_check_id(ncid, &ncp);
1048  if(stat != NC_NOERR) return stat;
1049  return ncp->dispatch->close(ncid);
1050 }
1051 
1150 int
1151 nc_set_fill(int ncid, int fillmode, int *old_modep)
1152 {
1153  NC* ncp;
1154  int stat = NC_check_id(ncid, &ncp);
1155  if(stat != NC_NOERR) return stat;
1156  return ncp->dispatch->set_fill(ncid,fillmode,old_modep);
1157 }
1158 
1170 int
1171 nc_inq_base_pe(int ncid, int *pe)
1172 {
1173  NC* ncp;
1174  int stat = NC_check_id(ncid, &ncp);
1175  if(stat != NC_NOERR) return stat;
1176  return ncp->dispatch->inq_base_pe(ncid,pe);
1177 }
1178 
1190 int
1191 nc_set_base_pe(int ncid, int pe)
1192 {
1193  NC* ncp;
1194  int stat = NC_check_id(ncid, &ncp);
1195  if(stat != NC_NOERR) return stat;
1196  return ncp->dispatch->set_base_pe(ncid,pe);
1197 }
1198 
1216 int
1217 nc_inq_format(int ncid, int *formatp)
1218 {
1219  NC* ncp;
1220  int stat = NC_check_id(ncid, &ncp);
1221  if(stat != NC_NOERR) return stat;
1222  return ncp->dispatch->inq_format(ncid,formatp);
1223 }
1224 
1269 int
1270 nc_inq(int ncid, int *ndimsp, int *nvarsp, int *nattsp, int *unlimdimidp)
1271 {
1272  NC* ncp;
1273  int stat = NC_check_id(ncid, &ncp);
1274  if(stat != NC_NOERR) return stat;
1275  return ncp->dispatch->inq(ncid,ndimsp,nvarsp,nattsp,unlimdimidp);
1276 }
1277 
1278 int
1279 nc_inq_nvars(int ncid, int *nvarsp)
1280 {
1281  NC* ncp;
1282  int stat = NC_check_id(ncid, &ncp);
1283  if(stat != NC_NOERR) return stat;
1284  return ncp->dispatch->inq(ncid, NULL, nvarsp, NULL, NULL);
1285 }
1286 
1352 int
1353 nc_inq_type(int ncid, nc_type xtype, char *name, size_t *size)
1354 {
1355  NC* ncp;
1356  /* For compatibility, we need to allow inq about
1357  atomic types, even if ncid is ill-defined */
1358  if(xtype <= ATOMICTYPEMAX) {
1359  if(xtype <= NC_NAT) return NC_EBADTYPE;
1360  if(name) strncpy(name,NC_atomictypename(xtype),NC_MAX_NAME);
1361  if(size) *size = NC_atomictypelen(xtype);
1362  return NC_NOERR;
1363  } else {
1364  int stat = NC_check_id(ncid, &ncp);
1365  if(stat != NC_NOERR) return NC_EBADTYPE; /* compatibility */
1366  return ncp->dispatch->inq_type(ncid,xtype,name,size);
1367  }
1368 }
1405 int
1406 NC_create(const char *path, int cmode, size_t initialsz,
1407  int basepe, size_t *chunksizehintp, int useparallel,
1408  void* mpi_info, int *ncidp)
1409 {
1410  int stat = NC_NOERR;
1411  NC* ncp = NULL;
1412  NC_Dispatch* dispatcher = NULL;
1413  /* Need three pieces of information for now */
1414  int model = 0; /* one of the NC_DISPATCH_XXX values */
1415  int isurl = 0; /* dap or cdmremote or neither */
1416  int xcmode = 0; /* for implied cmode flags */
1417  extern int default_create_format;
1418 
1419  /* Initialize the dispatch table. The function pointers in the
1420  * dispatch table will depend on how netCDF was built
1421  * (with/without netCDF-4, DAP, CDMREMOTE). */
1422  if(!nc_initialized)
1423  {
1424  if ((stat = NC_initialize()))
1425  return stat;
1426  /* Do local initialization */
1427  nc_local_initialize();
1428  nc_initialized = 1;
1429  }
1430 
1431  if((isurl = NC_testurl(path)))
1432  model = NC_urlmodel(path);
1433 
1434  /* Look to the incoming cmode for hints */
1435  if(model == 0) {
1436  if(cmode & NC_NETCDF4 || cmode & NC_PNETCDF)
1437  model = NC_DISPATCH_NC4;
1438  }
1439 
1440  if(model == 0) {
1441  /* Check default format */
1442  int format = default_create_format;
1443  switch (format) {
1444 #ifdef USE_NETCDF4
1445  case NC_FORMAT_NETCDF4:
1446  xcmode |= NC_NETCDF4;
1447  model = NC_DISPATCH_NC4;
1448  break;
1450  xcmode |= NC_CLASSIC_MODEL;
1451  model = NC_DISPATCH_NC4;
1452  break;
1453 #endif
1454  case NC_FORMAT_64BIT:
1455  xcmode |= NC_64BIT_OFFSET;
1456  /* fall thru */
1457  case NC_FORMAT_CLASSIC:
1458  default:
1459  model = NC_DISPATCH_NC3;
1460  break;
1461  }
1462  }
1463 
1464  /* Add inferred flags */
1465  cmode |= xcmode;
1466 
1467 #ifdef USE_NETCDF4
1468  if((cmode & NC_MPIIO && cmode & NC_MPIPOSIX))
1469  return NC_EINVAL;
1470 #endif
1471 
1472  if (!(dispatcher = NC_get_dispatch_override()))
1473  {
1474 
1475  /* Figure out what dispatcher to use */
1476 #ifdef USE_NETCDF4
1477 #ifdef USE_CDMREMOTE
1478  if(model == (NC_DISPATCH_NC4 | NC_DISPATCH_NCR))
1479  dispatcher = NCCR_dispatch_table;
1480  else
1481 #endif
1482  if(model == (NC_DISPATCH_NC4))
1483  dispatcher = NC4_dispatch_table;
1484  else
1485 #endif /*USE_NETCDF4*/
1486 #ifdef USE_DAP
1487  if(model == (NC_DISPATCH_NC3 | NC_DISPATCH_NCD))
1488  dispatcher = NCD3_dispatch_table;
1489  else
1490 #endif
1491  if(model == (NC_DISPATCH_NC3))
1492  dispatcher = NC3_dispatch_table;
1493  else
1494  return NC_ENOTNC;
1495  }
1496 
1497  if ((stat = dispatcher->create(path, cmode, initialsz, basepe, chunksizehintp,
1498  useparallel, mpi_info, dispatcher, &ncp)))
1499  return stat;
1500 
1501  ncp->dispatch = dispatcher;
1502  if(ncidp)
1503  *ncidp = ncp->ext_ncid;
1504  if (!(ncp->path = nulldup(path)))
1505  return NC_ENOMEM;
1506  return NC_NOERR;
1507 }
1508 
1524 int
1525 NC_open(const char *path, int cmode,
1526  int basepe, size_t *chunksizehintp,
1527  int useparallel, void* mpi_info,
1528  int *ncidp)
1529 {
1530  int stat = NC_NOERR;
1531  NC* ncp = NULL;
1532  NC_Dispatch* dispatcher = NULL;
1533  /* Need two pieces of information for now */
1534  int model = 0;
1535  int isurl = 0;
1536  int cdfversion = 0;
1537  int hdfversion = 0;
1538  extern int default_create_format;
1539 
1540  if(!nc_initialized) {
1541  stat = NC_initialize();
1542  if(stat) return stat;
1543  /* Do local initialization */
1544  nc_local_initialize();
1545  nc_initialized = 1;
1546  }
1547 
1548  isurl = NC_testurl(path);
1549  if(isurl)
1550  model = NC_urlmodel(path);
1551 
1552  if(!isurl) {
1553  /* Look at the file if it exists */
1554  stat = NC_check_file_type(path,useparallel,mpi_info,&cdfversion,&hdfversion);
1555  if(stat == NC_NOERR) {
1556  if(hdfversion != 0) {
1557  model = NC_DISPATCH_NC4;
1558  } else if(cdfversion != 0) {
1559  model = NC_DISPATCH_NC3;
1560  }
1561  }
1562  /* else ignore the file */
1563  }
1564 
1565  /* Look to the incoming cmode for hints */
1566  if(model == 0) {
1567  if(cmode & NC_NETCDF4 || cmode & NC_PNETCDF) model |= NC_DISPATCH_NC4;
1568  }
1569 
1570  if(model == 0) model = NC_DISPATCH_NC3; /* final default */
1571 
1572  /* Force flag consistentcy */
1573  if(model & NC_DISPATCH_NC4)
1574  cmode |= NC_NETCDF4;
1575  else if(model & NC_DISPATCH_NC3) {
1576  cmode &= ~NC_NETCDF4; /* must be netcdf-3 */
1577  if(cdfversion == 2) cmode |= NC_64BIT_OFFSET;
1578  }
1579 
1580  if((cmode & NC_MPIIO && cmode & NC_MPIPOSIX))
1581  return NC_EINVAL;
1582 
1583  /* override overrides any other table choice */
1584  dispatcher = NC_get_dispatch_override();
1585  if(dispatcher != NULL) goto havetable;
1586 
1587  /* Figure out what dispatcher to use */
1588 #if defined(USE_CDMREMOTE)
1589  if(model == (NC_DISPATCH_NC4 | NC_DISPATCH_NCR))
1590  dispatcher = NCCR_dispatch_table;
1591  else
1592 #endif
1593 #if defined(USE_DAP)
1594  if(model == (NC_DISPATCH_NC3 | NC_DISPATCH_NCD))
1595  dispatcher = NCD3_dispatch_table;
1596  else
1597 #endif
1598 #if defined(USE_NETCDF4)
1599  if(model == (NC_DISPATCH_NC4))
1600  dispatcher = NC4_dispatch_table;
1601  else
1602 #endif
1603  if(model == (NC_DISPATCH_NC3))
1604  dispatcher = NC3_dispatch_table;
1605  else
1606  return NC_ENOTNC;
1607 
1608  havetable:
1609  stat = dispatcher->open(path, cmode, basepe, chunksizehintp,
1610  useparallel, mpi_info, dispatcher, &ncp);
1611  if(stat == NC_NOERR) {
1612  ncp->dispatch = dispatcher;
1613  if(ncidp) *ncidp = ncp->ext_ncid;
1614  ncp->path = nulldup(path);
1615  if(path == NULL) stat = NC_ENOMEM;
1616  }
1617  return stat;
1618 }
1619 
1620 /*Provide an internal function for generating pseudo file descriptors
1621  for systems that are not file based (e.g. dap, memio).
1622 */
1623 
1624 /* Static counter for pseudo file descriptors (incremented) */
1625 static int pseudofd = 0;
1626 
1627 /* Create a pseudo file descriptor that does not
1628  overlap real file descriptors
1629 */
1630 int
1631 nc__pseudofd(void)
1632 {
1633  if(pseudofd == 0) {
1634  int maxfd = 32767; /* default */
1635 #ifdef HAVE_GETRLIMIT
1636  struct rlimit rl;
1637  if(getrlimit(RLIMIT_NOFILE,&rl) == 0) {
1638  if(rl.rlim_max != RLIM_INFINITY)
1639  maxfd = rl.rlim_max;
1640  if(rl.rlim_cur != RLIM_INFINITY)
1641  maxfd = rl.rlim_cur;
1642  }
1643  pseudofd = maxfd+1;
1644 #endif
1645  }
1646 
1647  return pseudofd++;
1648 }
1649 
1650 

Generated on Wed Aug 22 2012 14:39:39 for netCDF. NetCDF is a Unidata library.