nc4var.c 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485
  1. /*
  2. This file is part of netcdf-4, a netCDF-like interface for HDF5, or a
  3. HDF5 backend for netCDF, depending on your point of view.
  4. This file handles the nc4 variable functions.
  5. Copyright 2003-2006, University Corporation for Atmospheric
  6. Research. See COPYRIGHT file for copying and redistribution
  7. conditions.
  8. */
  9. #include <nc4internal.h>
  10. #include "nc4dispatch.h"
  11. #include <math.h>
  12. #ifdef USE_PNETCDF
  13. #include <pnetcdf.h>
  14. #endif
  15. /* Min and max deflate levels tolerated by HDF5. */
  16. #define MIN_DEFLATE_LEVEL 0
  17. #define MAX_DEFLATE_LEVEL 9
  18. /* This is to track opened HDF5 objects to make sure they are
  19. * closed. */
  20. #ifdef EXTRA_TESTS
  21. extern int num_plists;
  22. #endif /* EXTRA_TESTS */
  23. /* One meg is the minimum buffer size. */
  24. #define ONE_MEG 1048576
  25. /* Szip options. */
  26. #define NC_SZIP_EC_OPTION_MASK 4
  27. #define NC_SZIP_NN_OPTION_MASK 32
  28. #define NC_SZIP_MAX_PIXELS_PER_BLOCK 32
  29. int nc4_get_default_fill_value(NC_TYPE_INFO_T *type_info, void *fill_value);
  30. /* If the HDF5 dataset for this variable is open, then close it and
  31. * reopen it, with the perhaps new settings for chunk caching. */
  32. int
  33. nc4_reopen_dataset(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var)
  34. {
  35. hid_t access_pid;
  36. if (var->hdf_datasetid)
  37. {
  38. if ((access_pid = H5Pcreate(H5P_DATASET_ACCESS)) < 0)
  39. return NC_EHDFERR;
  40. #ifdef EXTRA_TESTS
  41. num_plists++;
  42. #endif
  43. if (H5Pset_chunk_cache(access_pid, var->chunk_cache_nelems,
  44. var->chunk_cache_size,
  45. var->chunk_cache_preemption) < 0)
  46. return NC_EHDFERR;
  47. if (H5Dclose(var->hdf_datasetid) < 0)
  48. return NC_EHDFERR;
  49. if ((var->hdf_datasetid = H5Dopen2(grp->hdf_grpid, var->name,
  50. access_pid)) < 0)
  51. return NC_EHDFERR;
  52. if (H5Pclose(access_pid) < 0)
  53. return NC_EHDFERR;
  54. #ifdef EXTRA_TESTS
  55. num_plists--;
  56. #endif
  57. if (var->dimscale)
  58. var->dim[0]->hdf_dimscaleid = var->hdf_datasetid;
  59. }
  60. return NC_NOERR;
  61. }
  62. /* Set chunk cache size for a variable. */
  63. int
  64. NC4_set_var_chunk_cache(int ncid, int varid, size_t size, size_t nelems,
  65. float preemption)
  66. {
  67. NC_FILE_INFO_T *nc;
  68. NC_GRP_INFO_T *grp;
  69. NC_HDF5_FILE_INFO_T *h5;
  70. NC_VAR_INFO_T *var;
  71. int retval;
  72. /* Check input for validity. */
  73. if (preemption < 0 || preemption > 1)
  74. return NC_EINVAL;
  75. /* Find info for this file and group, and set pointer to each. */
  76. if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5)))
  77. return retval;
  78. /* An attempt to do any of these things on a netCDF-3 file is
  79. * ignored with no error. */
  80. if (!h5)
  81. return NC_NOERR;
  82. assert(nc && grp && h5);
  83. /* Find the var. */
  84. for (var = grp->var; var; var = var->next)
  85. if (var->varid == varid)
  86. break;
  87. if (!var)
  88. return NC_ENOTVAR;
  89. /* Set the values. */
  90. var->chunk_cache_size = size;
  91. var->chunk_cache_nelems = nelems;
  92. var->chunk_cache_preemption = preemption;
  93. if ((retval = nc4_reopen_dataset(grp, var)))
  94. return retval;
  95. return NC_NOERR;
  96. }
  97. /* Need this version for fortran. Accept negative numbers to leave
  98. * settings as they are. */
  99. int
  100. nc_set_var_chunk_cache_ints(int ncid, int varid, int size, int nelems,
  101. int preemption)
  102. {
  103. size_t real_size = H5D_CHUNK_CACHE_NBYTES_DEFAULT;
  104. size_t real_nelems = H5D_CHUNK_CACHE_NSLOTS_DEFAULT;
  105. float real_preemption = H5D_CHUNK_CACHE_W0_DEFAULT;
  106. if (size >= 0)
  107. real_size = size * MEGABYTE;
  108. if (nelems >= 0)
  109. real_nelems = nelems;
  110. if (preemption >= 0)
  111. real_preemption = preemption / 100.;
  112. return nc_set_var_chunk_cache(ncid, varid, real_size, real_nelems,
  113. real_preemption);
  114. }
  115. /* Get chunk cache size for a variable. */
  116. int
  117. NC4_get_var_chunk_cache(int ncid, int varid, size_t *sizep,
  118. size_t *nelemsp, float *preemptionp)
  119. {
  120. NC_FILE_INFO_T *nc;
  121. NC_GRP_INFO_T *grp;
  122. NC_HDF5_FILE_INFO_T *h5;
  123. NC_VAR_INFO_T *var;
  124. int retval;
  125. /* Find info for this file and group, and set pointer to each. */
  126. if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5)))
  127. return retval;
  128. /* Attempting to do any of these things on a netCDF-3 file produces
  129. * an error. */
  130. if (!h5)
  131. return NC_ENOTNC4;
  132. assert(nc && grp && h5);
  133. /* Find the var. */
  134. for (var = grp->var; var; var = var->next)
  135. if (var->varid == varid)
  136. break;
  137. if (!var)
  138. return NC_ENOTVAR;
  139. /* Give the user what they want. */
  140. if (sizep)
  141. *sizep = var->chunk_cache_size;
  142. if (nelemsp)
  143. *nelemsp = var->chunk_cache_nelems;
  144. if (preemptionp)
  145. *preemptionp = var->chunk_cache_preemption;
  146. return NC_NOERR;
  147. }
  148. /* Get chunk cache size for a variable. */
  149. int
  150. nc_get_var_chunk_cache_ints(int ncid, int varid, int *sizep,
  151. int *nelemsp, int *preemptionp)
  152. {
  153. size_t real_size, real_nelems;
  154. float real_preemption;
  155. int ret;
  156. if ((ret = nc_get_var_chunk_cache(ncid, varid, &real_size,
  157. &real_nelems, &real_preemption)))
  158. return ret;
  159. if (sizep)
  160. *sizep = real_size / MEGABYTE;
  161. if (nelemsp)
  162. *nelemsp = (int)real_nelems;
  163. if(preemptionp)
  164. *preemptionp = (int)(real_preemption * 100);
  165. return NC_NOERR;
  166. }
  167. /* Check a set of chunksizes to see if they add up to a chunk that is too big. */
  168. static int
  169. check_chunksizes(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var, const size_t *chunksizes)
  170. {
  171. NC_TYPE_INFO_T *type_info;
  172. float total;
  173. size_t type_len;
  174. int d;
  175. int retval;
  176. if ((retval = nc4_get_typelen_mem(grp->file->nc4_info, var->xtype, 0, &type_len)))
  177. return retval;
  178. if ((retval = nc4_find_type(grp->file->nc4_info, var->xtype, &type_info)))
  179. return retval;
  180. if (type_info && type_info->class == NC_VLEN)
  181. total = sizeof(hvl_t);
  182. else
  183. total = type_len;
  184. for (d = 0; d < var->ndims; d++)
  185. {
  186. if (chunksizes[d] < 1)
  187. return NC_EINVAL;
  188. total *= chunksizes[d];
  189. }
  190. if (total > NC_MAX_UINT)
  191. return NC_EBADCHUNK;
  192. return NC_NOERR;
  193. }
  194. /* Find the default chunk nelems (i.e. length of chunk along each
  195. * dimension). */
  196. static int
  197. nc4_find_default_chunksizes2(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var)
  198. {
  199. int d;
  200. size_t type_size, max_len = 0;
  201. float num_values = 1, num_set = 0;
  202. int retval;
  203. #ifdef LOGGING
  204. int max_dim;
  205. float total_chunk_size;
  206. #endif
  207. if (var->type_info->nc_typeid == NC_STRING)
  208. type_size = sizeof(char *);
  209. else
  210. type_size = var->type_info->size;
  211. /* Later this will become the total number of bytes in the default
  212. * chunk. */
  213. #ifdef LOGGING
  214. total_chunk_size = type_size;
  215. #endif
  216. /* How many values in the variable (or one record, if there are
  217. * unlimited dimensions); which is the largest dimension, and how
  218. * long is it? */
  219. for (d = 0; d < var->ndims; d++)
  220. {
  221. assert(var->dim[d]);
  222. if (var->dim[d]->len)
  223. num_values *= (float)var->dim[d]->len;
  224. else
  225. num_set++;
  226. if (var->dim[d]->len > max_len)
  227. {
  228. max_len = var->dim[d]->len;
  229. #ifdef LOGGING
  230. max_dim = d;
  231. #endif
  232. }
  233. LOG((4, "d = %d max_dim %d max_len %ld num_values %f", d, max_dim, max_len,
  234. num_values));
  235. }
  236. /* If a dim is several orders of magnitude smaller than the max
  237. * dimension, set it's chunk size to the full extent of the smaller
  238. * dimension. */
  239. #define NC_DIM_MULTIPLIER 10000
  240. for (d = 0; d < var->ndims; d++)
  241. if (var->dim[d]->unlimited)
  242. var->chunksizes[d] = 1;
  243. else if (!var->dim[d]->unlimited && var->dim[d]->len * NC_DIM_MULTIPLIER < max_len)
  244. {
  245. var->chunksizes[d] = var->dim[d]->len;
  246. num_set++;
  247. }
  248. /* Pick a chunk length for each dimension, if one has not already
  249. * been picked above. */
  250. for (d = 0; d < var->ndims; d++)
  251. if (!var->chunksizes[d])
  252. {
  253. size_t suggested_size;
  254. suggested_size = (pow((double)DEFAULT_CHUNK_SIZE/(num_values * type_size),
  255. 1/(double)(var->ndims - num_set)) * var->dim[d]->len - .5);
  256. if (suggested_size > var->dim[d]->len)
  257. suggested_size = var->dim[d]->len;
  258. var->chunksizes[d] = suggested_size ? suggested_size : 1;
  259. LOG((4, "nc_def_var_nc4: name %s dim %d DEFAULT_CHUNK_SIZE %d num_values %f type_size %d "
  260. "chunksize %ld", var->name, d, DEFAULT_CHUNK_SIZE, num_values, type_size, var->chunksizes[d]));
  261. }
  262. /* Find total chunk size. */
  263. #ifdef LOGGING
  264. for (d = 0; d < var->ndims; d++)
  265. total_chunk_size *= var->chunksizes[d];
  266. LOG((4, "total_chunk_size %f", total_chunk_size));
  267. #endif
  268. /* But did this add up to a chunk that is too big? */
  269. retval = check_chunksizes(grp, var, var->chunksizes);
  270. if (retval)
  271. {
  272. /* Other error? */
  273. if (retval != NC_EBADCHUNK)
  274. return retval;
  275. /* Chunk is too big! Reduce each dimension by half and try again. */
  276. for ( ; retval == NC_EBADCHUNK; retval = check_chunksizes(grp, var, var->chunksizes))
  277. for (d = 0; d < var->ndims; d++)
  278. var->chunksizes[d] = var->chunksizes[d]/2 ? var->chunksizes[d]/2 : 1;
  279. }
  280. /* Do we have any big data overhangs? They can be dangerous to
  281. * babies, the elderly, or confused campers who have had too much
  282. * beer. */
  283. for (d = 0; d < var->ndims; d++)
  284. {
  285. int num_chunks;
  286. size_t overhang;
  287. assert(var->chunksizes[d] > 0);
  288. num_chunks = (var->dim[d]->len + var->chunksizes[d] - 1) / var->chunksizes[d];
  289. if(num_chunks > 0) {
  290. overhang = (num_chunks * var->chunksizes[d]) - var->dim[d]->len;
  291. var->chunksizes[d] -= overhang / num_chunks;
  292. }
  293. }
  294. return NC_NOERR;
  295. }
  296. /* This is called when a new netCDF-4 variable is defined. Break it
  297. * down! */
  298. static int
  299. nc_def_var_nc4(int ncid, const char *name, nc_type xtype,
  300. int ndims, const int *dimidsp, int *varidp)
  301. {
  302. NC_GRP_INFO_T *grp;
  303. NC_VAR_INFO_T *var;
  304. NC_DIM_INFO_T *dim;
  305. NC_HDF5_FILE_INFO_T *h5;
  306. NC_TYPE_INFO_T *type_info;
  307. char norm_name[NC_MAX_NAME + 1];
  308. int new_varid = 0;
  309. int num_unlim = 0;
  310. int d;
  311. size_t num_values = 1;
  312. int retval;
  313. /* Find info for this file and group, and set pointer to each. */
  314. if ((retval = nc4_find_grp_h5(ncid, &grp, &h5)))
  315. return retval;
  316. assert(grp && h5);
  317. /* If it's not in define mode, strict nc3 files error out,
  318. * otherwise switch to define mode. */
  319. if (!(h5->flags & NC_INDEF))
  320. {
  321. if (h5->cmode & NC_CLASSIC_MODEL)
  322. return NC_ENOTINDEFINE;
  323. if ((retval = NC4_redef(ncid)))
  324. return retval;
  325. }
  326. /* Check and normalize the name. */
  327. if ((retval = nc4_check_name(name, norm_name)))
  328. return retval;
  329. /* Not a Type is, well, not a type.*/
  330. if (xtype == NC_NAT)
  331. return NC_EBADTYPE;
  332. /* For classic files, only classic types are allowed. */
  333. if (h5->cmode & NC_CLASSIC_MODEL && xtype > NC_DOUBLE)
  334. return NC_ESTRICTNC3;
  335. /* If this is a user defined type, find it. */
  336. if (xtype > NC_STRING)
  337. if (nc4_find_type(grp->file->nc4_info, xtype, &type_info))
  338. return NC_EBADTYPE;
  339. /* cast needed for braindead systems with signed size_t */
  340. if((unsigned long) ndims > X_INT_MAX) /* Backward compat */
  341. return NC_EINVAL;
  342. /* Classic model files have a limit on number of vars. */
  343. if(h5->cmode & NC_CLASSIC_MODEL && h5->nvars >= NC_MAX_VARS)
  344. return NC_EMAXVARS;
  345. /* Check that this name is not in use as a var, grp, or type. */
  346. if ((retval = nc4_check_dup_name(grp, norm_name)))
  347. return retval;
  348. /* If the file is read-only, return an error. */
  349. if (h5->no_write)
  350. return NC_EPERM;
  351. /* Get the new varid. */
  352. for (var = grp->var; var; var = var->next)
  353. new_varid++;
  354. /* Check all the dimids to make sure they exist. */
  355. for (d = 0; d < ndims; d++)
  356. {
  357. if ((retval = nc4_find_dim(grp, dimidsp[d], &dim, NULL)))
  358. return retval;
  359. if (dim->unlimited)
  360. num_unlim++;
  361. else
  362. num_values *= dim->len;
  363. }
  364. /* These degrubbing messages sure are handy! */
  365. LOG((3, "nc_def_var_nc4: name %s type %d ndims %d", norm_name, xtype, ndims));
  366. #ifdef LOGGING
  367. {
  368. int dd;
  369. for (dd = 0; dd < ndims; dd++)
  370. LOG((4, "dimid[%d] %d", dd, dimidsp[dd]));
  371. }
  372. #endif
  373. /* Add the var to the end of the list. */
  374. if ((retval = nc4_var_list_add(&grp->var, &var)))
  375. return retval;
  376. /* Now fill in the values in the var info structure. */
  377. if (!(var->name = malloc((strlen(norm_name) + 1) * sizeof(char))))
  378. return NC_ENOMEM;
  379. strcpy(var->name, norm_name);
  380. var->varid = grp->nvars++;
  381. var->xtype = xtype;
  382. var->ndims = ndims;
  383. var->dirty++;
  384. /* If this is a user-defined type, there is a type_info stuct with
  385. * all the type information. For atomic types, fake up a type_info
  386. * struct. */
  387. if (xtype > NC_STRING)
  388. var->type_info = type_info;
  389. else
  390. {
  391. if (!(var->type_info = calloc(1, sizeof(NC_TYPE_INFO_T))))
  392. return NC_ENOMEM;
  393. var->type_info->nc_typeid = xtype;
  394. if ((retval = nc4_get_hdf_typeid(h5, var->xtype, &var->type_info->hdf_typeid,
  395. var->type_info->endianness)))
  396. return retval;
  397. if ((var->type_info->native_typeid = H5Tget_native_type(var->type_info->hdf_typeid,
  398. H5T_DIR_DEFAULT)) < 0)
  399. return NC_EHDFERR;
  400. if ((retval = nc4_get_typelen_mem(h5, var->type_info->nc_typeid, 0,
  401. &var->type_info->size)))
  402. return retval;
  403. }
  404. if (!num_unlim)
  405. var->contiguous = 1;
  406. /* Allocate space for dimension information. */
  407. if (ndims)
  408. {
  409. if (!(var->dim = calloc(ndims, sizeof(NC_DIM_INFO_T *))))
  410. return NC_ENOMEM;
  411. if (!(var->dimids = calloc(ndims, sizeof(int))))
  412. return NC_ENOMEM;
  413. }
  414. /* At the same time, check to see if this is a coordinate
  415. * variable. If so, it will have the same name as one of its
  416. * dimensions. If it is a coordinate var, is it a coordinate var in
  417. * the same group as the dim? */
  418. for (d = 0; d < ndims; d++)
  419. {
  420. NC_GRP_INFO_T *dim_grp;
  421. if ((retval = nc4_find_dim(grp, dimidsp[d], &dim, &dim_grp)))
  422. return retval;
  423. if (strcmp(dim->name, norm_name) == 0 && dim_grp == grp && d == 0)
  424. {
  425. var->dimscale++;
  426. dim->coord_var = var;
  427. dim->coord_var_in_grp++;
  428. }
  429. var->dimids[d] = dimidsp[d];
  430. var->dim[d] = dim;
  431. }
  432. /* Determine default chunksizes for this variable. (Even for
  433. * variables which may be contiguous. */
  434. LOG((4, "allocating array of %d size_t to hold chunksizes for var %s",
  435. var->ndims, var->name));
  436. if (var->ndims)
  437. if (!(var->chunksizes = calloc(var->ndims, sizeof(size_t))))
  438. return NC_ENOMEM;
  439. if ((retval = nc4_find_default_chunksizes2(grp, var)))
  440. return retval;
  441. /* Is this a variable with a chunksize greater than the current
  442. * cache size? */
  443. if ((retval = nc4_adjust_var_cache(grp, var)))
  444. return retval;
  445. /* If the user names this variable the same as a dimension, but
  446. * doesn't use that dimension first in its list of dimension ids,
  447. * is not a coordinate variable. I need to change its HDF5 name,
  448. * because the dimension will cause a HDF5 dataset to be created,
  449. * and this var has the same name. */
  450. for (dim = grp->dim; dim; dim = dim->next)
  451. if (!strcmp(dim->name, norm_name) &&
  452. (!var->ndims || dimidsp[0] != dim->dimid))
  453. {
  454. /* Set a different hdf5 name for this variable to avoid name
  455. * clash. */
  456. if (strlen(norm_name) + strlen(NON_COORD_PREPEND) > NC_MAX_NAME)
  457. return NC_EMAXNAME;
  458. if (!(var->hdf5_name = malloc((strlen(NON_COORD_PREPEND) +
  459. strlen(norm_name) + 1) * sizeof(char))))
  460. return NC_ENOMEM;
  461. sprintf(var->hdf5_name, "%s%s", NON_COORD_PREPEND, norm_name);
  462. }
  463. /* If this is a coordinate var, it is marked as a HDF5 dimension
  464. * scale. (We found dim above.) Otherwise, allocate space to
  465. * remember whether dimension scales have been attached to each
  466. * dimension. */
  467. if (!var->dimscale && ndims)
  468. if (ndims && !(var->dimscale_attached = calloc(ndims, sizeof(int))))
  469. return NC_ENOMEM;
  470. /* Return the varid. */
  471. if (varidp)
  472. *varidp = var->varid;
  473. LOG((4, "new varid %d", var->varid));
  474. return retval;
  475. }
  476. /* Create a new variable to hold user data. This is what it's all
  477. * about baby! */
  478. int
  479. NC4_def_var(int ncid, const char *name, nc_type xtype, int ndims,
  480. const int *dimidsp, int *varidp)
  481. {
  482. NC_FILE_INFO_T *nc;
  483. LOG((2, "nc_def_var: ncid 0x%x name %s xtype %d ndims %d",
  484. ncid, name, xtype, ndims));
  485. /* If there are dimensions, I need their ids. */
  486. if (ndims && !dimidsp)
  487. return NC_EINVAL;
  488. /* Find metadata for this file. */
  489. if (!(nc = nc4_find_nc_file(ncid)))
  490. return NC_EBADID;
  491. #ifdef USE_PNETCDF
  492. /* Take care of files created/opened with parallel-netcdf library. */
  493. if (nc->pnetcdf_file)
  494. {
  495. int ret;
  496. ret = ncmpi_def_var(nc->int_ncid, name, xtype, ndims,
  497. dimidsp, varidp);
  498. nc->pnetcdf_ndims[*varidp] = ndims;
  499. return ret;
  500. }
  501. #endif /* USE_PNETCDF */
  502. /* Netcdf-3 cases handled by dispatch layer. */
  503. assert(nc->nc4_info);
  504. /* Handle netcdf-4 cases. */
  505. return nc_def_var_nc4(ncid, name, xtype, ndims, dimidsp, varidp);
  506. }
  507. /* Get all the information about a variable. Pass NULL for whatever
  508. * you don't care about. This is an internal function, not exposed to
  509. * the user. */
  510. int
  511. NC4_inq_var_all(int ncid, int varid, char *name, nc_type *xtypep,
  512. int *ndimsp, int *dimidsp, int *nattsp,
  513. int *shufflep, int *deflatep, int *deflate_levelp,
  514. int *fletcher32p, int *contiguousp, size_t *chunksizesp,
  515. int *no_fill, void *fill_valuep, int *endiannessp,
  516. int *options_maskp, int *pixels_per_blockp)
  517. {
  518. NC_FILE_INFO_T *nc;
  519. NC_GRP_INFO_T *grp;
  520. NC_HDF5_FILE_INFO_T *h5;
  521. NC_VAR_INFO_T *var;
  522. NC_ATT_INFO_T *att;
  523. int natts=0;
  524. size_t type_size;
  525. int d;
  526. int retval;
  527. LOG((2, "nc_inq_var_all: ncid 0x%x varid %d", ncid, varid));
  528. /* Find info for this file and group, and set pointer to each. */
  529. if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5)))
  530. return retval;
  531. assert(nc && grp && h5);
  532. #ifdef USE_PNETCDF
  533. /* Take care of files created/opened with parallel-netcdf library. */
  534. if (nc->pnetcdf_file)
  535. return ncmpi_inq_var(nc->int_ncid, varid, name, xtypep, ndimsp,
  536. dimidsp, nattsp);
  537. #endif /* USE_PNETCDF */
  538. /* Walk through the list of vars, and return the info about the one
  539. with a matching varid. If the varid is -1, find the global
  540. atts and call it a day. */
  541. if (varid == NC_GLOBAL)
  542. {
  543. if (nattsp)
  544. {
  545. for (att = grp->att; att; att = att->next)
  546. natts++;
  547. *nattsp = natts;
  548. }
  549. return NC_NOERR;
  550. }
  551. /* Find the var. */
  552. for (var = grp->var; var; var = var->next)
  553. if (var->varid == varid)
  554. break;
  555. /* Oh no! Maybe we couldn't find it (*sob*)! */
  556. if (!var)
  557. return NC_ENOTVAR;
  558. /* Copy the data to the user's data buffers. */
  559. if (name)
  560. strcpy(name, var->name);
  561. if (xtypep)
  562. *xtypep = var->xtype;
  563. if (ndimsp)
  564. *ndimsp = var->ndims;
  565. if (dimidsp)
  566. for (d = 0; d < var->ndims; d++)
  567. dimidsp[d] = var->dimids[d];
  568. if (nattsp)
  569. {
  570. for (att = var->att; att; att = att->next)
  571. natts++;
  572. *nattsp = natts;
  573. }
  574. /* Chunking stuff. */
  575. if (!var->contiguous && chunksizesp)
  576. for (d = 0; d < var->ndims; d++)
  577. {
  578. chunksizesp[d] = var->chunksizes[d];
  579. LOG((4, "chunksizesp[%d]=%d", d, chunksizesp[d]));
  580. }
  581. if (contiguousp)
  582. *contiguousp = var->contiguous ? NC_CONTIGUOUS : NC_CHUNKED;
  583. /* Filter stuff. */
  584. if (deflatep)
  585. *deflatep = var->deflate;
  586. if (deflate_levelp)
  587. *deflate_levelp = var->deflate_level;
  588. if (shufflep)
  589. *shufflep = var->shuffle;
  590. if (fletcher32p)
  591. *fletcher32p = var->fletcher32;
  592. if (options_maskp)
  593. *options_maskp = var->options_mask;
  594. if (pixels_per_blockp)
  595. *pixels_per_blockp = var->pixels_per_block;
  596. /* Fill value stuff. */
  597. if (no_fill)
  598. *no_fill = var->no_fill;
  599. /* Don't do a thing with fill_valuep if no_fill mode is set for
  600. * this var, or if fill_valuep is NULL. */
  601. if (!var->no_fill && fill_valuep)
  602. {
  603. /* Do we have a fill value for this var? */
  604. if (var->fill_value)
  605. {
  606. if ((retval = nc4_get_typelen_mem(grp->file->nc4_info, var->xtype, 0, &type_size)))
  607. return retval;
  608. memcpy(fill_valuep, var->fill_value, type_size);
  609. }
  610. else
  611. {
  612. if ((retval = nc4_get_default_fill_value(var->type_info, fill_valuep)))
  613. return retval;
  614. }
  615. }
  616. /* Does the user want the endianness of this variable? */
  617. if (endiannessp)
  618. *endiannessp = var->type_info->endianness;
  619. return NC_NOERR;
  620. }
  621. /* This functions sets extra stuff about a netCDF-4 variable which
  622. must be set before the enddef but after the def_var. This is an
  623. internal function, deliberately hidden from the user so that we can
  624. change the prototype of this functions without changing the API. */
  625. static int
  626. nc_def_var_extra(int ncid, int varid, int *shuffle, int *deflate,
  627. int *deflate_level, int *fletcher32, int *contiguous,
  628. const size_t *chunksizes, int *no_fill,
  629. const void *fill_value, int *endianness,
  630. int *options_mask, int *pixels_per_block)
  631. {
  632. NC_FILE_INFO_T *nc;
  633. NC_GRP_INFO_T *grp;
  634. NC_HDF5_FILE_INFO_T *h5;
  635. NC_VAR_INFO_T *var;
  636. NC_DIM_INFO_T *dim;
  637. size_t type_size;
  638. int d;
  639. int retval;
  640. LOG((2, "nc_def_var_extra: ncid 0x%x varid %d", ncid, varid));
  641. /* Find info for this file and group, and set pointer to each. */
  642. if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5)))
  643. return retval;
  644. /* Attempting to do any of these things on a netCDF-3 file produces
  645. * an error. */
  646. if (!h5)
  647. return NC_ENOTNC4;
  648. assert(nc && grp && h5);
  649. /* Find the var. */
  650. for (var = grp->var; var; var = var->next)
  651. if (var->varid == varid)
  652. break;
  653. /* Oh no! Maybe we couldn't find it (*sob*)! */
  654. if (!var)
  655. return NC_ENOTVAR;
  656. /* Can't turn on contiguous and deflate/fletcher32/szip. */
  657. if (contiguous)
  658. if ((*contiguous != NC_CHUNKED && deflate) ||
  659. (*contiguous != NC_CHUNKED && fletcher32) ||
  660. (*contiguous != NC_CHUNKED && options_mask))
  661. return NC_EINVAL;
  662. /* If the HDF5 dataset has already been created, then it is too
  663. * late to set all the extra stuff. */
  664. if (var->created)
  665. return NC_ELATEDEF;
  666. /* Check compression options. */
  667. if ((deflate && options_mask) ||
  668. (deflate && !deflate_level) ||
  669. (options_mask && !pixels_per_block))
  670. return NC_EINVAL;
  671. /* Valid deflate level? */
  672. if (deflate && deflate_level)
  673. {
  674. if (*deflate)
  675. if (*deflate_level < MIN_DEFLATE_LEVEL ||
  676. *deflate_level > MAX_DEFLATE_LEVEL)
  677. return NC_EINVAL;
  678. if (var->options_mask)
  679. return NC_EINVAL;
  680. /* For scalars, just ignore attempt to deflate. */
  681. if (!var->ndims)
  682. return NC_NOERR;
  683. /* Well, if we couldn't find any errors, I guess we have to take
  684. * the users settings. Darn! */
  685. var->contiguous = 0;
  686. var->deflate = *deflate;
  687. if (*deflate)
  688. var->deflate_level = *deflate_level;
  689. LOG((3, "nc_def_var_extra: *deflate_level %d", *deflate_level));
  690. }
  691. /* Szip in use? */
  692. if (options_mask)
  693. {
  694. #ifndef USE_SZIP
  695. return NC_EINVAL;
  696. #endif
  697. if (var->deflate)
  698. return NC_EINVAL;
  699. if ((*options_mask != NC_SZIP_EC_OPTION_MASK) &&
  700. (*options_mask != NC_SZIP_NN_OPTION_MASK))
  701. return NC_EINVAL;
  702. if ((*pixels_per_block > NC_SZIP_MAX_PIXELS_PER_BLOCK) ||
  703. (var->type_info->nc_typeid >= NC_STRING))
  704. return NC_EINVAL;
  705. var->options_mask = *options_mask;
  706. var->pixels_per_block = *pixels_per_block;
  707. var->contiguous = 0;
  708. }
  709. /* Shuffle filter? */
  710. if (shuffle)
  711. {
  712. var->shuffle = *shuffle;
  713. var->contiguous = 0;
  714. }
  715. /* Fltcher32 checksum error protection? */
  716. if (fletcher32)
  717. {
  718. var->fletcher32 = *fletcher32;
  719. var->contiguous = 0;
  720. }
  721. /* Does the user want a contiguous dataset? Not so fast! Make sure
  722. * that there are no unlimited dimensions, and no filters in use
  723. * for this data. */
  724. if (contiguous && *contiguous)
  725. {
  726. if (var->deflate || var->fletcher32 || var->shuffle || var->options_mask)
  727. return NC_EINVAL;
  728. for (d = 0; d < var->ndims; d++)
  729. {
  730. if ((retval = nc4_find_dim(grp, var->dimids[d], &dim, NULL)))
  731. return retval;
  732. if (dim->unlimited)
  733. return NC_EINVAL;
  734. }
  735. var->contiguous = NC_CONTIGUOUS;
  736. }
  737. /* Chunksizes anyone? */
  738. if (contiguous && *contiguous == NC_CHUNKED)
  739. {
  740. var->contiguous = 0;
  741. /* If the user provided chunksizes, check that they are not too
  742. * big, and that their total size of chunk is less than 4 GB. */
  743. if (chunksizes)
  744. {
  745. if ((retval = check_chunksizes(grp, var, chunksizes)))
  746. return retval;
  747. /* Set the chunksizes for this variable. */
  748. for (d = 0; d < var->ndims; d++)
  749. var->chunksizes[d] = chunksizes[d];
  750. }
  751. }
  752. /* Is this a variable with a chunksize greater than the current
  753. * cache size? */
  754. if (var->contiguous == NC_CHUNKED && (chunksizes || deflate || contiguous))
  755. {
  756. /* Determine default chunksizes for this variable. */
  757. if (!var->chunksizes[0])
  758. if ((retval = nc4_find_default_chunksizes2(grp, var)))
  759. return retval;
  760. /* Adjust the cache. */
  761. if ((retval = nc4_adjust_var_cache(grp, var)))
  762. return retval;
  763. }
  764. /* Are we setting a fill modes? */
  765. if (no_fill)
  766. {
  767. if (*no_fill)
  768. var->no_fill = 1;
  769. else
  770. var->no_fill = 0;
  771. }
  772. /* Are we setting a fill value? */
  773. if (fill_value && !var->no_fill)
  774. {
  775. /* If fill value hasn't been set, allocate space. */
  776. if ((retval = nc4_get_typelen_mem(h5, var->xtype, 0, &type_size)))
  777. return retval;
  778. if (!var->fill_value)
  779. if (!(var->fill_value = malloc(type_size)))
  780. return NC_ENOMEM;
  781. /* Copy the fill_value. */
  782. LOG((4, "Copying fill value into metadata for variable %s",
  783. var->name));
  784. memcpy(var->fill_value, fill_value, type_size);
  785. /* If there's a _FillValue attribute, delete it. */
  786. retval = nc_del_att(ncid, varid, _FillValue);
  787. if (retval && retval != NC_ENOTATT)
  788. return retval;
  789. /* Create a _FillValue attribute. */
  790. if ((retval = nc_put_att(ncid, varid, _FillValue, var->xtype, 1, fill_value)))
  791. return retval;
  792. }
  793. /* Is the user setting the endianness? */
  794. if (endianness)
  795. var->type_info->endianness = *endianness;
  796. return NC_NOERR;
  797. }
  798. /* Set the deflate level for a var, lower is faster, higher is
  799. * better. Must be called after nc_def_var and before nc_enddef or any
  800. * functions which writes data to the file. */
  801. int
  802. NC4_def_var_deflate(int ncid, int varid, int shuffle, int deflate,
  803. int deflate_level)
  804. {
  805. return nc_def_var_extra(ncid, varid, &shuffle, &deflate,
  806. &deflate_level, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
  807. }
  808. /* Set checksum for a var. This must be called after the nc_def_var
  809. * but before the nc_enddef. */
  810. int
  811. NC4_def_var_fletcher32(int ncid, int varid, int fletcher32)
  812. {
  813. return nc_def_var_extra(ncid, varid, NULL, NULL, NULL, &fletcher32,
  814. NULL, NULL, NULL, NULL, NULL, NULL, NULL);
  815. }
  816. /* Define chunking stuff for a var. This must be done after nc_def_var
  817. and before nc_enddef.
  818. Chunking is required in any dataset with one or more unlimited
  819. dimension in HDF5, or any dataset using a filter.
  820. Where chunksize is a pointer to an array of size ndims, with the
  821. chunksize in each dimension.
  822. */
  823. int
  824. NC4_def_var_chunking(int ncid, int varid, int contiguous, const size_t *chunksizesp)
  825. {
  826. return nc_def_var_extra(ncid, varid, NULL, NULL, NULL, NULL,
  827. &contiguous, chunksizesp, NULL, NULL, NULL, NULL, NULL);
  828. }
  829. /* Inquire about chunking stuff for a var. This is a private,
  830. * undocumented function, used by the f77 API to avoid size_t
  831. * problems. */
  832. int
  833. nc_inq_var_chunking_ints(int ncid, int varid, int *contiguousp, int *chunksizesp)
  834. {
  835. NC_FILE_INFO_T *nc;
  836. NC_GRP_INFO_T *grp;
  837. NC_HDF5_FILE_INFO_T *h5;
  838. NC_VAR_INFO_T *var;
  839. size_t *cs = NULL;
  840. int i, retval;
  841. /* Find this ncid's file info. */
  842. if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5)))
  843. return retval;
  844. assert(nc);
  845. /* Must be netcdf-4. */
  846. if (!h5)
  847. return NC_ENOTNC4;
  848. /* Find var cause I need the number of dims. */
  849. if ((retval = nc4_find_g_var_nc(nc, ncid, varid, &grp, &var)))
  850. return retval;
  851. /* Allocate space for the size_t copy of the chunksizes array. */
  852. if (var->ndims)
  853. if (!(cs = malloc(var->ndims * sizeof(size_t))))
  854. return NC_ENOMEM;
  855. retval = NC4_inq_var_all(ncid, varid, NULL, NULL, NULL, NULL, NULL,
  856. NULL, NULL, NULL, NULL, contiguousp, cs, NULL,
  857. NULL, NULL, NULL, NULL);
  858. /* Copy to size_t array. */
  859. if (*contiguousp == NC_CHUNKED)
  860. for (i = 0; i < var->ndims; i++)
  861. {
  862. chunksizesp[i] = cs[i];
  863. if (cs[i] > NC_MAX_INT)
  864. retval = NC_ERANGE;
  865. }
  866. if (var->ndims)
  867. free(cs);
  868. return retval;
  869. }
  870. /* This function defines the chunking with ints, which works better
  871. * with F77 portability. It is a secret function, which has been
  872. * rendered unmappable, and it is impossible to apparate anywhere in
  873. * this function. */
  874. int
  875. nc_def_var_chunking_ints(int ncid, int varid, int contiguous, int *chunksizesp)
  876. {
  877. NC_FILE_INFO_T *nc;
  878. NC_GRP_INFO_T *grp;
  879. NC_HDF5_FILE_INFO_T *h5;
  880. NC_VAR_INFO_T *var;
  881. size_t *cs = NULL;
  882. int i, retval;
  883. /* Find this ncid's file info. */
  884. if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5)))
  885. return retval;
  886. assert(nc);
  887. /* Must be netcdf-4. */
  888. if (!h5)
  889. return NC_ENOTNC4;
  890. /* Find var cause I need the number of dims. */
  891. if ((retval = nc4_find_g_var_nc(nc, ncid, varid, &grp, &var)))
  892. return retval;
  893. /* Allocate space for the size_t copy of the chunksizes array. */
  894. if (var->ndims)
  895. if (!(cs = malloc(var->ndims * sizeof(size_t))))
  896. return NC_ENOMEM;
  897. /* Copy to size_t array. */
  898. for (i = 0; i < var->ndims; i++)
  899. cs[i] = chunksizesp[i];
  900. retval = nc_def_var_extra(ncid, varid, NULL, NULL, NULL, NULL,
  901. &contiguous, cs, NULL, NULL, NULL, NULL, NULL);
  902. if (var->ndims)
  903. free(cs);
  904. return retval;
  905. }
  906. /* Define fill value behavior for a variable. This must be done after
  907. nc_def_var and before nc_enddef. */
  908. int
  909. NC4_def_var_fill(int ncid, int varid, int no_fill, const void *fill_value)
  910. {
  911. return nc_def_var_extra(ncid, varid, NULL, NULL, NULL, NULL, NULL,
  912. NULL, &no_fill, fill_value, NULL, NULL, NULL);
  913. }
  914. /* Define the endianness of a variable. */
  915. int
  916. NC4_def_var_endian(int ncid, int varid, int endianness)
  917. {
  918. return nc_def_var_extra(ncid, varid, NULL, NULL, NULL, NULL, NULL,
  919. NULL, NULL, NULL, &endianness, NULL, NULL);
  920. }
  921. /* Get var id from name. */
  922. int
  923. NC4_inq_varid(int ncid, const char *name, int *varidp)
  924. {
  925. NC_FILE_INFO_T *nc;
  926. NC_GRP_INFO_T *grp;
  927. NC_HDF5_FILE_INFO_T *h5;
  928. NC_VAR_INFO_T *var;
  929. char norm_name[NC_MAX_NAME + 1];
  930. int retval;
  931. if (!name)
  932. return NC_EINVAL;
  933. if (!varidp)
  934. return NC_NOERR;
  935. LOG((2, "nc_inq_varid: ncid 0x%x name %s", ncid, name));
  936. /* Find info for this file and group, and set pointer to each. */
  937. if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5)))
  938. return retval;
  939. /* Handle netcdf-3. */
  940. assert(h5);
  941. /* Normalize name. */
  942. if ((retval = nc4_normalize_name(name, norm_name)))
  943. return retval;
  944. /* Find var of this name. */
  945. for (var = grp->var; var; var = var->next)
  946. if (!(strcmp(var->name, norm_name)))
  947. {
  948. *varidp = var->varid;
  949. return NC_NOERR;
  950. }
  951. return NC_ENOTVAR;
  952. }
  953. /* Rename a var to "bubba," for example.
  954. According to the netcdf-3.5 docs: If the new name is longer than
  955. the old name, the netCDF dataset must be in define mode. */
  956. int
  957. NC4_rename_var(int ncid, int varid, const char *name)
  958. {
  959. NC_FILE_INFO_T *nc;
  960. NC_GRP_INFO_T *grp;
  961. NC_HDF5_FILE_INFO_T *h5;
  962. NC_VAR_INFO_T *var;
  963. int retval = NC_NOERR;
  964. LOG((2, "nc_rename_var: ncid 0x%x varid %d name %s",
  965. ncid, varid, name));
  966. /* Find info for this file and group, and set pointer to each. */
  967. if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5)))
  968. return retval;
  969. #ifdef USE_PNETCDF
  970. /* Take care of files created/opened with parallel-netcdf library. */
  971. if (nc->pnetcdf_file)
  972. return ncmpi_rename_var(nc->int_ncid, varid, name);
  973. #endif /* USE_PNETCDF */
  974. /* Take care of netcdf-3 files. */
  975. assert(h5);
  976. /* Is the new name too long? */
  977. if (strlen(name) > NC_MAX_NAME)
  978. return NC_EMAXNAME;
  979. /* Trying to write to a read-only file? No way, Jose! */
  980. if (h5->no_write)
  981. return NC_EPERM;
  982. /* Check name validity, if strict nc3 rules are in effect for this
  983. * file. */
  984. if ((retval = NC_check_name(name)))
  985. return retval;
  986. /* Is name in use? */
  987. for (var = grp->var; var; var = var->next)
  988. if (!strncmp(var->name, name, NC_MAX_NAME))
  989. return NC_ENAMEINUSE;
  990. /* Find the var. */
  991. for (var = grp->var; var; var = var->next)
  992. if (var->varid == varid)
  993. break;
  994. if (!var)
  995. return NC_ENOTVAR;
  996. /* If we're not in define mode, new name must be of equal or
  997. less size, if strict nc3 rules are in effect for this . */
  998. if (!(h5->flags & NC_INDEF) && strlen(name) > strlen(var->name) &&
  999. (h5->cmode & NC_CLASSIC_MODEL))
  1000. return NC_ENOTINDEFINE;
  1001. /* Change the HDF5 file, if this var has already been created
  1002. there. */
  1003. if (var->created)
  1004. {
  1005. if (H5Gmove(grp->hdf_grpid, var->name, name) < 0)
  1006. BAIL(NC_EHDFERR);
  1007. }
  1008. /* Now change the name in our metadata. */
  1009. free(var->name);
  1010. if (!(var->name = malloc((strlen(name) + 1) * sizeof(char))))
  1011. return NC_ENOMEM;
  1012. strcpy(var->name, name);
  1013. exit:
  1014. return retval;
  1015. }
  1016. int
  1017. NC4_var_par_access(int ncid, int varid, int par_access)
  1018. {
  1019. #ifndef USE_PARALLEL
  1020. return NC_ENOPAR;
  1021. #else
  1022. NC_FILE_INFO_T *nc;
  1023. NC_GRP_INFO_T *grp;
  1024. NC_HDF5_FILE_INFO_T *h5;
  1025. NC_VAR_INFO_T *var;
  1026. int retval;
  1027. LOG((1, "nc_var_par_access: ncid 0x%x varid %d par_access %d", ncid,
  1028. varid, par_access));
  1029. if (par_access != NC_INDEPENDENT && par_access != NC_COLLECTIVE)
  1030. return NC_EINVAL;
  1031. /* Find info for this file and group, and set pointer to each. */
  1032. if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5)))
  1033. return retval;
  1034. #ifdef USE_PNETCDF
  1035. /* Handle files opened/created with parallel-netcdf library. */
  1036. if (nc->pnetcdf_file)
  1037. {
  1038. if (par_access == nc->pnetcdf_access_mode)
  1039. return NC_NOERR;
  1040. nc->pnetcdf_access_mode = par_access;
  1041. if (par_access == NC_INDEPENDENT)
  1042. return ncmpi_begin_indep_data(nc->int_ncid);
  1043. else
  1044. return ncmpi_end_indep_data(nc->int_ncid);
  1045. }
  1046. #endif /* USE_PNETCDF */
  1047. /* This function only for files opened with nc_open_par or nc_create_par. */
  1048. if (!h5->parallel)
  1049. return NC_ENOPAR;
  1050. /* Find the var, and set its preference. */
  1051. for (var = grp->var; var; var = var->next)
  1052. if (var->varid == varid)
  1053. break;
  1054. if (!var)
  1055. return NC_ENOTVAR;
  1056. if (par_access)
  1057. var->parallel_access = NC_COLLECTIVE;
  1058. else
  1059. var->parallel_access = NC_INDEPENDENT;
  1060. return NC_NOERR;
  1061. #endif /* USE_PARALLEL */
  1062. }
  1063. static int
  1064. nc4_put_vara_tc(int ncid, int varid, nc_type mem_type, int mem_type_is_long,
  1065. const size_t *startp, const size_t *countp, const void *op)
  1066. {
  1067. NC_FILE_INFO_T *nc;
  1068. LOG((2, "nc4_put_vara_tc: ncid 0x%x varid %d mem_type %d mem_type_is_long %d",
  1069. ncid, varid, mem_type, mem_type_is_long));
  1070. if (!(nc = nc4_find_nc_file(ncid)))
  1071. return NC_EBADID;
  1072. #ifdef USE_PNETCDF
  1073. /* Handle files opened/created with the parallel-netcdf library. */
  1074. if (nc->pnetcdf_file)
  1075. {
  1076. MPI_Offset mpi_start[NC_MAX_DIMS], mpi_count[NC_MAX_DIMS];
  1077. int d;
  1078. /* No NC_LONGs for parallel-netcdf library! */
  1079. if (mem_type_is_long)
  1080. return NC_EINVAL;
  1081. /* We must convert the start, count, and stride arrays to
  1082. * MPI_Offset type. */
  1083. for (d = 0; d < nc->pnetcdf_ndims[varid]; d++)
  1084. {
  1085. mpi_start[d] = startp[d];
  1086. mpi_count[d] = countp[d];
  1087. }
  1088. if (nc->pnetcdf_access_mode == NC_INDEPENDENT)
  1089. {
  1090. switch(mem_type)
  1091. {
  1092. case NC_BYTE:
  1093. return ncmpi_put_vara_schar(nc->int_ncid, varid, mpi_start, mpi_count, op);
  1094. case NC_UBYTE:
  1095. return ncmpi_put_vara_uchar(nc->int_ncid, varid, mpi_start, mpi_count, op);
  1096. case NC_CHAR:
  1097. return ncmpi_put_vara_text(nc->int_ncid, varid, mpi_start, mpi_count, op);
  1098. case NC_SHORT:
  1099. return ncmpi_put_vara_short(nc->int_ncid, varid, mpi_start, mpi_count, op);
  1100. case NC_INT:
  1101. return ncmpi_put_vara_int(nc->int_ncid, varid, mpi_start, mpi_count, op);
  1102. case NC_FLOAT:
  1103. return ncmpi_put_vara_float(nc->int_ncid, varid, mpi_start, mpi_count, op);
  1104. case NC_DOUBLE:
  1105. return ncmpi_put_vara_double(nc->int_ncid, varid, mpi_start, mpi_count, op);
  1106. case NC_NAT:
  1107. default:
  1108. return NC_EBADTYPE;
  1109. }
  1110. }
  1111. else
  1112. {
  1113. switch(mem_type)
  1114. {
  1115. case NC_BYTE:
  1116. return ncmpi_put_vara_schar_all(nc->int_ncid, varid, mpi_start, mpi_count, op);
  1117. case NC_UBYTE:
  1118. return ncmpi_put_vara_uchar_all(nc->int_ncid, varid, mpi_start, mpi_count, op);
  1119. case NC_CHAR:
  1120. return ncmpi_put_vara_text_all(nc->int_ncid, varid, mpi_start, mpi_count, op);
  1121. case NC_SHORT:
  1122. return ncmpi_put_vara_short_all(nc->int_ncid, varid, mpi_start, mpi_count, op);
  1123. case NC_INT:
  1124. return ncmpi_put_vara_int_all(nc->int_ncid, varid, mpi_start, mpi_count, op);
  1125. case NC_FLOAT:
  1126. return ncmpi_put_vara_float_all(nc->int_ncid, varid, mpi_start, mpi_count, op);
  1127. case NC_DOUBLE:
  1128. return ncmpi_put_vara_double_all(nc->int_ncid, varid, mpi_start, mpi_count, op);
  1129. case NC_NAT:
  1130. default:
  1131. return NC_EBADTYPE;
  1132. }
  1133. }
  1134. }
  1135. #endif /* USE_PNETCDF */
  1136. /* NetCDF-3 cases handled by dispatch layer. */
  1137. assert(nc->nc4_info);
  1138. return nc4_put_vara(nc, ncid, varid, startp, countp, mem_type,
  1139. mem_type_is_long, (void *)op);
  1140. }
  1141. int
  1142. nc4_get_hdf4_vara(NC_FILE_INFO_T *nc, int ncid, int varid, const size_t *startp,
  1143. const size_t *countp, nc_type mem_nc_type, int is_long, void *data)
  1144. {
  1145. #ifdef USE_HDF4
  1146. NC_GRP_INFO_T *grp, *g;
  1147. NC_HDF5_FILE_INFO_T *h5;
  1148. NC_VAR_INFO_T *var;
  1149. NC_DIM_INFO_T *dim;
  1150. int32 start32[NC_MAX_VAR_DIMS], edge32[NC_MAX_VAR_DIMS];
  1151. int retval, d;
  1152. /* Find our metadata for this file, group, and var. */
  1153. assert(nc);
  1154. if ((retval = nc4_find_g_var_nc(nc, ncid, varid, &grp, &var)))
  1155. return retval;
  1156. h5 = nc->nc4_info;
  1157. assert(grp && h5 && var && var->name);
  1158. for (d = 0; d < var->ndims; d++)
  1159. {
  1160. start32[d] = startp[d];
  1161. edge32[d] = countp[d];
  1162. }
  1163. if (SDreaddata(var->sdsid, start32, NULL, edge32, data))
  1164. return NC_EHDFERR;
  1165. #endif /* USE_HDF4 */
  1166. return NC_NOERR;
  1167. }
  1168. /* Get an array. */
  1169. static int
  1170. nc4_get_vara_tc(int ncid, int varid, nc_type mem_type, int mem_type_is_long,
  1171. const size_t *startp, const size_t *countp, void *ip)
  1172. {
  1173. NC_FILE_INFO_T *nc;
  1174. LOG((2, "nc4_get_vara_tc: ncid 0x%x varid %d mem_type %d mem_type_is_long %d",
  1175. ncid, varid, mem_type, mem_type_is_long));
  1176. if (!(nc = nc4_find_nc_file(ncid)))
  1177. return NC_EBADID;
  1178. #ifdef USE_PNETCDF
  1179. /* Handle files opened/created with the parallel-netcdf library. */
  1180. if (nc->pnetcdf_file)
  1181. {
  1182. MPI_Offset mpi_start[NC_MAX_VAR_DIMS], mpi_count[NC_MAX_VAR_DIMS];
  1183. int d;
  1184. /* No NC_LONGs for parallel-netcdf library! */
  1185. if (mem_type_is_long)
  1186. return NC_EINVAL;
  1187. /* We must convert the start, count, and stride arrays to
  1188. * MPI_Offset type. */
  1189. for (d = 0; d < nc->pnetcdf_ndims[varid]; d++)
  1190. {
  1191. mpi_start[d] = startp[d];
  1192. mpi_count[d] = countp[d];
  1193. }
  1194. if (nc->pnetcdf_access_mode == NC_INDEPENDENT)
  1195. {
  1196. switch(mem_type)
  1197. {
  1198. case NC_BYTE:
  1199. return ncmpi_get_vara_schar(nc->int_ncid, varid, mpi_start, mpi_count, ip);
  1200. case NC_UBYTE:
  1201. return ncmpi_get_vara_uchar(nc->int_ncid, varid, mpi_start, mpi_count, ip);
  1202. case NC_CHAR:
  1203. return ncmpi_get_vara_text(nc->int_ncid, varid, mpi_start, mpi_count, ip);
  1204. case NC_SHORT:
  1205. return ncmpi_get_vara_short(nc->int_ncid, varid, mpi_start, mpi_count, ip);
  1206. case NC_INT:
  1207. return ncmpi_get_vara_int(nc->int_ncid, varid, mpi_start, mpi_count, ip);
  1208. case NC_FLOAT:
  1209. return ncmpi_get_vara_float(nc->int_ncid, varid, mpi_start, mpi_count, ip);
  1210. case NC_DOUBLE:
  1211. return ncmpi_get_vara_double(nc->int_ncid, varid, mpi_start, mpi_count, ip);
  1212. case NC_NAT:
  1213. default:
  1214. return NC_EBADTYPE;
  1215. }
  1216. }
  1217. else
  1218. {
  1219. switch(mem_type)
  1220. {
  1221. case NC_BYTE:
  1222. return ncmpi_get_vara_schar_all(nc->int_ncid, varid, mpi_start, mpi_count, ip);
  1223. case NC_UBYTE:
  1224. return ncmpi_get_vara_uchar_all(nc->int_ncid, varid, mpi_start, mpi_count, ip);
  1225. case NC_CHAR:
  1226. return ncmpi_get_vara_text_all(nc->int_ncid, varid, mpi_start, mpi_count, ip);
  1227. case NC_SHORT:
  1228. return ncmpi_get_vara_short_all(nc->int_ncid, varid, mpi_start, mpi_count, ip);
  1229. case NC_INT:
  1230. return ncmpi_get_vara_int_all(nc->int_ncid, varid, mpi_start, mpi_count, ip);
  1231. case NC_FLOAT:
  1232. return ncmpi_get_vara_float_all(nc->int_ncid, varid, mpi_start, mpi_count, ip);
  1233. case NC_DOUBLE:
  1234. return ncmpi_get_vara_double_all(nc->int_ncid, varid, mpi_start, mpi_count, ip);
  1235. case NC_NAT:
  1236. default:
  1237. return NC_EBADTYPE;
  1238. }
  1239. }
  1240. }
  1241. #endif /* USE_PNETCDF */
  1242. /* Handle netCDF-3 cases. */
  1243. assert(nc->nc4_info);
  1244. /* Handle HDF4 cases. */
  1245. if (nc->nc4_info->hdf4)
  1246. return nc4_get_hdf4_vara(nc, ncid, varid, startp, countp, mem_type,
  1247. mem_type_is_long, (void *)ip);
  1248. /* Handle HDF5 cases. */
  1249. return nc4_get_vara(nc, ncid, varid, startp, countp, mem_type,
  1250. mem_type_is_long, (void *)ip);
  1251. }
  1252. int
  1253. NC4_put_vara(int ncid, int varid, const size_t *startp,
  1254. const size_t *countp, const void *op, int memtype)
  1255. {
  1256. return nc4_put_vara_tc(ncid, varid, memtype, 0, startp, countp, op);
  1257. }
  1258. /* Read an array of values. */
  1259. int
  1260. NC4_get_vara(int ncid, int varid, const size_t *startp,
  1261. const size_t *countp, void *ip, int memtype)
  1262. {
  1263. return nc4_get_vara_tc(ncid, varid, memtype, 0, startp, countp, ip);
  1264. }