nc.c 31 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559
  1. /*
  2. * Copyright 1996, University Corporation for Atmospheric Research
  3. * See netcdf/COPYRIGHT file for copying and redistribution conditions.
  4. */
  5. #include <config.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include <assert.h>
  9. #if defined(LOCKNUMREC) /* && _CRAYMPP */
  10. # include <mpp/shmem.h>
  11. # include <intrinsics.h>
  12. #endif
  13. #ifdef HAVE_UNISTD_H
  14. #include <unistd.h>
  15. #endif
  16. #include "nc.h"
  17. #include "ncdispatch.h"
  18. #include "nc3dispatch.h"
  19. #include "rnd.h"
  20. #include "ncx.h"
  21. /* This is the default create format for nc_create and nc__create. */
  22. int default_create_format = NC_FORMAT_CLASSIC;
  23. /* These have to do with version numbers. */
  24. #define MAGIC_NUM_LEN 4
  25. #define VER_CLASSIC 1
  26. #define VER_64BIT_OFFSET 2
  27. #define VER_HDF5 3
  28. int
  29. NC_check_id(int ncid, NC **ncpp)
  30. {
  31. NC* nc = find_in_NCList(ncid);
  32. if(nc == NULL) return NC_EBADID;
  33. if(ncpp) *ncpp = nc;
  34. return NC_NOERR;
  35. }
  36. static void
  37. free_NC(NC *ncp)
  38. {
  39. if(ncp == NULL)
  40. return;
  41. free_NC_dimarrayV(&ncp->dims);
  42. free_NC_attrarrayV(&ncp->attrs);
  43. free_NC_vararrayV(&ncp->vars);
  44. if (ncp->path)
  45. free(ncp->path);
  46. #if _CRAYMPP && defined(LOCKNUMREC)
  47. shfree(ncp);
  48. #else
  49. free(ncp);
  50. #endif /* _CRAYMPP && LOCKNUMREC */
  51. }
  52. static NC *
  53. new_NC(const size_t *chunkp, NC_Dispatch* dispatch)
  54. {
  55. NC *ncp;
  56. int stat = dispatch->new_nc(&ncp);
  57. if(stat) return NULL;
  58. ncp->xsz = MIN_NC_XSZ;
  59. assert(ncp->xsz == ncx_len_NC(ncp,0));
  60. ncp->chunk = chunkp != NULL ? *chunkp : NC_SIZEHINT_DEFAULT;
  61. return ncp;
  62. }
  63. static NC *
  64. dup_NC(const NC *ref)
  65. {
  66. NC *ncp;
  67. int stat = ref->dispatch->new_nc(&ncp);
  68. if(stat) return NULL;
  69. if(ncp == NULL)
  70. return NULL;
  71. if(dup_NC_dimarrayV(&ncp->dims, &ref->dims) != NC_NOERR)
  72. goto err;
  73. if(dup_NC_attrarrayV(&ncp->attrs, &ref->attrs) != NC_NOERR)
  74. goto err;
  75. if(dup_NC_vararrayV(&ncp->vars, &ref->vars) != NC_NOERR)
  76. goto err;
  77. ncp->xsz = ref->xsz;
  78. ncp->begin_var = ref->begin_var;
  79. ncp->begin_rec = ref->begin_rec;
  80. ncp->recsize = ref->recsize;
  81. NC_set_numrecs(ncp, NC_get_numrecs(ref));
  82. return ncp;
  83. err:
  84. free_NC(ncp);
  85. return NULL;
  86. }
  87. /*
  88. * Verify that this is a user nc_type
  89. * Formerly
  90. NCcktype()
  91. * Sense of the return is changed.
  92. */
  93. int
  94. nc_cktype(nc_type type)
  95. {
  96. switch((int)type){
  97. case NC_BYTE:
  98. case NC_CHAR:
  99. case NC_SHORT:
  100. case NC_INT:
  101. case NC_FLOAT:
  102. case NC_DOUBLE:
  103. return(NC_NOERR);
  104. }
  105. return(NC_EBADTYPE);
  106. }
  107. /*
  108. * How many objects of 'type'
  109. * will fit into xbufsize?
  110. */
  111. size_t
  112. ncx_howmany(nc_type type, size_t xbufsize)
  113. {
  114. switch(type){
  115. case NC_BYTE:
  116. case NC_CHAR:
  117. return xbufsize;
  118. case NC_SHORT:
  119. return xbufsize/X_SIZEOF_SHORT;
  120. case NC_INT:
  121. return xbufsize/X_SIZEOF_INT;
  122. case NC_FLOAT:
  123. return xbufsize/X_SIZEOF_FLOAT;
  124. case NC_DOUBLE:
  125. return xbufsize/X_SIZEOF_DOUBLE;
  126. default:
  127. assert("ncx_howmany: Bad type" == 0);
  128. return(0);
  129. }
  130. }
  131. #define D_RNDUP(x, align) _RNDUP(x, (off_t)(align))
  132. /*
  133. * Compute each variable's 'begin' offset,
  134. * update 'begin_rec' as well.
  135. */
  136. static int
  137. NC_begins(NC *ncp,
  138. size_t h_minfree, size_t v_align,
  139. size_t v_minfree, size_t r_align)
  140. {
  141. size_t ii;
  142. int sizeof_off_t;
  143. off_t index = 0;
  144. NC_var **vpp;
  145. NC_var *last = NULL;
  146. if(v_align == NC_ALIGN_CHUNK)
  147. v_align = ncp->chunk;
  148. if(r_align == NC_ALIGN_CHUNK)
  149. r_align = ncp->chunk;
  150. if (fIsSet(ncp->flags, NC_64BIT_OFFSET)) {
  151. sizeof_off_t = 8;
  152. } else {
  153. sizeof_off_t = 4;
  154. }
  155. ncp->xsz = ncx_len_NC(ncp,sizeof_off_t);
  156. if(ncp->vars.nelems == 0)
  157. return NC_NOERR;
  158. /* only (re)calculate begin_var if there is not sufficient space in header
  159. or start of non-record variables is not aligned as requested by valign */
  160. if (ncp->begin_var < ncp->xsz + h_minfree ||
  161. ncp->begin_var != D_RNDUP(ncp->begin_var, v_align) )
  162. {
  163. index = (off_t) ncp->xsz;
  164. ncp->begin_var = D_RNDUP(index, v_align);
  165. if(ncp->begin_var < index + h_minfree)
  166. {
  167. ncp->begin_var = D_RNDUP(index + (off_t)h_minfree, v_align);
  168. }
  169. }
  170. index = ncp->begin_var;
  171. /* loop thru vars, first pass is for the 'non-record' vars */
  172. vpp = ncp->vars.value;
  173. for(ii = 0; ii < ncp->vars.nelems ; ii++, vpp++)
  174. {
  175. if( IS_RECVAR(*vpp) )
  176. {
  177. /* skip record variables on this pass */
  178. continue;
  179. }
  180. #if 0
  181. fprintf(stderr, " VAR %d %s: %ld\n", ii, (*vpp)->name->cp, (long)index);
  182. #endif
  183. if( sizeof_off_t == 4 && (index > X_OFF_MAX || index < 0) )
  184. {
  185. return NC_EVARSIZE;
  186. }
  187. (*vpp)->begin = index;
  188. index += (*vpp)->len;
  189. }
  190. /* only (re)calculate begin_rec if there is not sufficient
  191. space at end of non-record variables or if start of record
  192. variables is not aligned as requested by r_align */
  193. if (ncp->begin_rec < index + v_minfree ||
  194. ncp->begin_rec != D_RNDUP(ncp->begin_rec, r_align) )
  195. {
  196. ncp->begin_rec = D_RNDUP(index, r_align);
  197. if(ncp->begin_rec < index + v_minfree)
  198. {
  199. ncp->begin_rec = D_RNDUP(index + (off_t)v_minfree, r_align);
  200. }
  201. }
  202. index = ncp->begin_rec;
  203. ncp->recsize = 0;
  204. /* loop thru vars, second pass is for the 'record' vars */
  205. vpp = (NC_var **)ncp->vars.value;
  206. for(ii = 0; ii < ncp->vars.nelems; ii++, vpp++)
  207. {
  208. if( !IS_RECVAR(*vpp) )
  209. {
  210. /* skip non-record variables on this pass */
  211. continue;
  212. }
  213. #if 0
  214. fprintf(stderr, " REC %d %s: %ld\n", ii, (*vpp)->name->cp, (long)index);
  215. #endif
  216. if( sizeof_off_t == 4 && (index > X_OFF_MAX || index < 0) )
  217. {
  218. return NC_EVARSIZE;
  219. }
  220. (*vpp)->begin = index;
  221. index += (*vpp)->len;
  222. /* check if record size must fit in 32-bits */
  223. #if SIZEOF_OFF_T == SIZEOF_SIZE_T && SIZEOF_SIZE_T == 4
  224. if( ncp->recsize > X_UINT_MAX - (*vpp)->len )
  225. {
  226. return NC_EVARSIZE;
  227. }
  228. #endif
  229. if((*vpp)->len != UINT32_MAX) /* flag for vars >= 2**32 bytes */
  230. ncp->recsize += (*vpp)->len;
  231. last = (*vpp);
  232. }
  233. /*
  234. * for special case of
  235. */
  236. if(last != NULL) {
  237. if(ncp->recsize == last->len) { /* exactly one record variable, pack value */
  238. ncp->recsize = *last->dsizes * last->xsz;
  239. } else if(last->len == UINT32_MAX) { /* huge last record variable */
  240. ncp->recsize += *last->dsizes * last->xsz;
  241. }
  242. }
  243. if(NC_IsNew(ncp))
  244. NC_set_numrecs(ncp, 0);
  245. return NC_NOERR;
  246. }
  247. /*
  248. * Read just the numrecs member.
  249. * (A relatively expensive way to do things.)
  250. */
  251. int
  252. read_numrecs(NC *ncp)
  253. {
  254. int status = NC_NOERR;
  255. const void *xp = NULL;
  256. size_t nrecs = NC_get_numrecs(ncp);
  257. assert(!NC_indef(ncp));
  258. #define NC_NUMRECS_OFFSET 4
  259. #define NC_NUMRECS_EXTENT 4
  260. status = ncio_get(ncp->nciop,
  261. NC_NUMRECS_OFFSET, NC_NUMRECS_EXTENT, 0, (void **)&xp);
  262. /* cast away const */
  263. if(status != NC_NOERR)
  264. return status;
  265. status = ncx_get_size_t(&xp, &nrecs);
  266. (void) ncio_rel(ncp->nciop, NC_NUMRECS_OFFSET, 0);
  267. if(status == NC_NOERR)
  268. {
  269. NC_set_numrecs(ncp, nrecs);
  270. fClr(ncp->flags, NC_NDIRTY);
  271. }
  272. return status;
  273. }
  274. /*
  275. * Write out just the numrecs member.
  276. * (A relatively expensive way to do things.)
  277. */
  278. int
  279. write_numrecs(NC *ncp)
  280. {
  281. int status = NC_NOERR;
  282. void *xp = NULL;
  283. assert(!NC_readonly(ncp));
  284. assert(!NC_indef(ncp));
  285. status = ncio_get(ncp->nciop,
  286. NC_NUMRECS_OFFSET, NC_NUMRECS_EXTENT, RGN_WRITE, &xp);
  287. if(status != NC_NOERR)
  288. return status;
  289. {
  290. const size_t nrecs = NC_get_numrecs(ncp);
  291. status = ncx_put_size_t(&xp, &nrecs);
  292. }
  293. (void) ncio_rel(ncp->nciop, NC_NUMRECS_OFFSET, RGN_MODIFIED);
  294. if(status == NC_NOERR)
  295. fClr(ncp->flags, NC_NDIRTY);
  296. return status;
  297. }
  298. /*
  299. * Read in the header
  300. * It is expensive.
  301. */
  302. static int
  303. read_NC(NC *ncp)
  304. {
  305. int status = NC_NOERR;
  306. free_NC_dimarrayV(&ncp->dims);
  307. free_NC_attrarrayV(&ncp->attrs);
  308. free_NC_vararrayV(&ncp->vars);
  309. status = nc_get_NC(ncp);
  310. if(status == NC_NOERR)
  311. fClr(ncp->flags, NC_NDIRTY | NC_HDIRTY);
  312. return status;
  313. }
  314. /*
  315. * Write out the header
  316. */
  317. static int
  318. write_NC(NC *ncp)
  319. {
  320. int status = NC_NOERR;
  321. assert(!NC_readonly(ncp));
  322. status = ncx_put_NC(ncp, NULL, 0, 0);
  323. if(status == NC_NOERR)
  324. fClr(ncp->flags, NC_NDIRTY | NC_HDIRTY);
  325. return status;
  326. }
  327. /*
  328. * Write the header or the numrecs if necessary.
  329. */
  330. int
  331. NC_sync(NC *ncp)
  332. {
  333. assert(!NC_readonly(ncp));
  334. if(NC_hdirty(ncp))
  335. {
  336. return write_NC(ncp);
  337. }
  338. /* else */
  339. if(NC_ndirty(ncp))
  340. {
  341. return write_numrecs(ncp);
  342. }
  343. /* else */
  344. return NC_NOERR;
  345. }
  346. /*
  347. * Initialize the 'non-record' variables.
  348. */
  349. static int
  350. fillerup(NC *ncp)
  351. {
  352. int status = NC_NOERR;
  353. size_t ii;
  354. NC_var **varpp;
  355. assert(!NC_readonly(ncp));
  356. assert(NC_dofill(ncp));
  357. /* loop thru vars */
  358. varpp = ncp->vars.value;
  359. for(ii = 0; ii < ncp->vars.nelems; ii++, varpp++)
  360. {
  361. if(IS_RECVAR(*varpp))
  362. {
  363. /* skip record variables */
  364. continue;
  365. }
  366. status = fill_NC_var(ncp, *varpp, (*varpp)->len, 0);
  367. if(status != NC_NOERR)
  368. break;
  369. }
  370. return status;
  371. }
  372. /* Begin endef */
  373. /*
  374. */
  375. static int
  376. fill_added_recs(NC *gnu, NC *old)
  377. {
  378. NC_var ** const gnu_varpp = (NC_var **)gnu->vars.value;
  379. const int old_nrecs = (int) NC_get_numrecs(old);
  380. int recno = 0;
  381. NC_var **vpp = gnu_varpp;
  382. NC_var *const *const end = &vpp[gnu->vars.nelems];
  383. int numrecvars = 0;
  384. /* Determine if there is only one record variable. If so, we
  385. must treat as a special case because there's no record padding */
  386. for(; vpp < end; vpp++) {
  387. if(IS_RECVAR(*vpp)) {
  388. numrecvars++;
  389. }
  390. }
  391. for(; recno < old_nrecs; recno++)
  392. {
  393. int varid = (int)old->vars.nelems;
  394. for(; varid < (int)gnu->vars.nelems; varid++)
  395. {
  396. const NC_var *const gnu_varp = *(gnu_varpp + varid);
  397. if(!IS_RECVAR(gnu_varp))
  398. {
  399. /* skip non-record variables */
  400. continue;
  401. }
  402. /* else */
  403. {
  404. size_t varsize = numrecvars == 1 ? gnu->recsize : gnu_varp->len;
  405. const int status = fill_NC_var(gnu, gnu_varp, varsize, recno);
  406. if(status != NC_NOERR)
  407. return status;
  408. }
  409. }
  410. }
  411. return NC_NOERR;
  412. }
  413. /*
  414. */
  415. static int
  416. fill_added(NC *gnu, NC *old)
  417. {
  418. NC_var ** const gnu_varpp = (NC_var **)gnu->vars.value;
  419. int varid = (int)old->vars.nelems;
  420. for(; varid < (int)gnu->vars.nelems; varid++)
  421. {
  422. const NC_var *const gnu_varp = *(gnu_varpp + varid);
  423. if(IS_RECVAR(gnu_varp))
  424. {
  425. /* skip record variables */
  426. continue;
  427. }
  428. /* else */
  429. {
  430. const int status = fill_NC_var(gnu, gnu_varp, gnu_varp->len, 0);
  431. if(status != NC_NOERR)
  432. return status;
  433. }
  434. }
  435. return NC_NOERR;
  436. }
  437. /*
  438. * Move the records "out".
  439. * Fill as needed.
  440. */
  441. static int
  442. move_recs_r(NC *gnu, NC *old)
  443. {
  444. int status;
  445. int recno;
  446. int varid;
  447. NC_var **gnu_varpp = (NC_var **)gnu->vars.value;
  448. NC_var **old_varpp = (NC_var **)old->vars.value;
  449. NC_var *gnu_varp;
  450. NC_var *old_varp;
  451. off_t gnu_off;
  452. off_t old_off;
  453. const size_t old_nrecs = NC_get_numrecs(old);
  454. /* Don't parallelize this loop */
  455. for(recno = (int)old_nrecs -1; recno >= 0; recno--)
  456. {
  457. /* Don't parallelize this loop */
  458. for(varid = (int)old->vars.nelems -1; varid >= 0; varid--)
  459. {
  460. gnu_varp = *(gnu_varpp + varid);
  461. if(!IS_RECVAR(gnu_varp))
  462. {
  463. /* skip non-record variables on this pass */
  464. continue;
  465. }
  466. /* else */
  467. /* else, a pre-existing variable */
  468. old_varp = *(old_varpp + varid);
  469. gnu_off = gnu_varp->begin + (off_t)(gnu->recsize * recno);
  470. old_off = old_varp->begin + (off_t)(old->recsize * recno);
  471. if(gnu_off == old_off)
  472. continue; /* nothing to do */
  473. assert(gnu_off > old_off);
  474. status = ncio_move(gnu->nciop, gnu_off, old_off,
  475. old_varp->len, 0);
  476. if(status != NC_NOERR)
  477. return status;
  478. }
  479. }
  480. NC_set_numrecs(gnu, old_nrecs);
  481. return NC_NOERR;
  482. }
  483. /*
  484. * Move the "non record" variables "out".
  485. * Fill as needed.
  486. */
  487. static int
  488. move_vars_r(NC *gnu, NC *old)
  489. {
  490. int status;
  491. int varid;
  492. NC_var **gnu_varpp = (NC_var **)gnu->vars.value;
  493. NC_var **old_varpp = (NC_var **)old->vars.value;
  494. NC_var *gnu_varp;
  495. NC_var *old_varp;
  496. off_t gnu_off;
  497. off_t old_off;
  498. /* Don't parallelize this loop */
  499. for(varid = (int)old->vars.nelems -1;
  500. varid >= 0; varid--)
  501. {
  502. gnu_varp = *(gnu_varpp + varid);
  503. if(IS_RECVAR(gnu_varp))
  504. {
  505. /* skip record variables on this pass */
  506. continue;
  507. }
  508. /* else */
  509. old_varp = *(old_varpp + varid);
  510. gnu_off = gnu_varp->begin;
  511. old_off = old_varp->begin;
  512. if(gnu_off == old_off)
  513. continue; /* nothing to do */
  514. assert(gnu_off > old_off);
  515. status = ncio_move(gnu->nciop, gnu_off, old_off,
  516. old_varp->len, 0);
  517. if(status != NC_NOERR)
  518. return status;
  519. }
  520. return NC_NOERR;
  521. }
  522. /*
  523. * Given a valid ncp, return NC_EVARSIZE if any variable has a bad len
  524. * (product of non-rec dim sizes too large), else return NC_NOERR.
  525. */
  526. static int
  527. NC_check_vlens(NC *ncp)
  528. {
  529. NC_var **vpp;
  530. /* maximum permitted variable size (or size of one record's worth
  531. of a record variable) in bytes. This is different for format 1
  532. and format 2. */
  533. size_t vlen_max;
  534. size_t ii;
  535. size_t large_vars_count;
  536. size_t rec_vars_count;
  537. int last = 0;
  538. if(ncp->vars.nelems == 0)
  539. return NC_NOERR;
  540. if ((ncp->flags & NC_64BIT_OFFSET) && sizeof(off_t) > 4) {
  541. /* CDF2 format and LFS */
  542. vlen_max = X_UINT_MAX - 3; /* "- 3" handles rounded-up size */
  543. } else {
  544. /* CDF1 format */
  545. vlen_max = X_INT_MAX - 3;
  546. }
  547. /* Loop through vars, first pass is for non-record variables. */
  548. large_vars_count = 0;
  549. rec_vars_count = 0;
  550. vpp = ncp->vars.value;
  551. for (ii = 0; ii < ncp->vars.nelems; ii++, vpp++) {
  552. if( !IS_RECVAR(*vpp) ) {
  553. last = 0;
  554. if( NC_check_vlen(*vpp, vlen_max) == 0 ) {
  555. large_vars_count++;
  556. last = 1;
  557. }
  558. } else {
  559. rec_vars_count++;
  560. }
  561. }
  562. /* OK if last non-record variable size too large, since not used to
  563. compute an offset */
  564. if( large_vars_count > 1) { /* only one "too-large" variable allowed */
  565. return NC_EVARSIZE;
  566. }
  567. /* and it has to be the last one */
  568. if( large_vars_count == 1 && last == 0) {
  569. return NC_EVARSIZE;
  570. }
  571. if( rec_vars_count > 0 ) {
  572. /* and if it's the last one, there can't be any record variables */
  573. if( large_vars_count == 1 && last == 1) {
  574. return NC_EVARSIZE;
  575. }
  576. /* Loop through vars, second pass is for record variables. */
  577. large_vars_count = 0;
  578. vpp = ncp->vars.value;
  579. for (ii = 0; ii < ncp->vars.nelems; ii++, vpp++) {
  580. if( IS_RECVAR(*vpp) ) {
  581. last = 0;
  582. if( NC_check_vlen(*vpp, vlen_max) == 0 ) {
  583. large_vars_count++;
  584. last = 1;
  585. }
  586. }
  587. }
  588. /* OK if last record variable size too large, since not used to
  589. compute an offset */
  590. if( large_vars_count > 1) { /* only one "too-large" variable allowed */
  591. return NC_EVARSIZE;
  592. }
  593. /* and it has to be the last one */
  594. if( large_vars_count == 1 && last == 0) {
  595. return NC_EVARSIZE;
  596. }
  597. }
  598. return NC_NOERR;
  599. }
  600. /*
  601. * End define mode.
  602. * Common code for ncendef, ncclose(endef)
  603. * Flushes I/O buffers.
  604. */
  605. static int
  606. NC_endef(NC *ncp,
  607. size_t h_minfree, size_t v_align,
  608. size_t v_minfree, size_t r_align)
  609. {
  610. int status = NC_NOERR;
  611. assert(!NC_readonly(ncp));
  612. assert(NC_indef(ncp));
  613. status = NC_check_vlens(ncp);
  614. if(status != NC_NOERR)
  615. return status;
  616. status = NC_begins(ncp, h_minfree, v_align, v_minfree, r_align);
  617. if(status != NC_NOERR)
  618. return status;
  619. if(ncp->old != NULL)
  620. {
  621. /* a plain redef, not a create */
  622. assert(!NC_IsNew(ncp));
  623. assert(fIsSet(ncp->flags, NC_INDEF));
  624. assert(ncp->begin_rec >= ncp->old->begin_rec);
  625. assert(ncp->begin_var >= ncp->old->begin_var);
  626. if(ncp->vars.nelems != 0)
  627. {
  628. if(ncp->begin_rec > ncp->old->begin_rec)
  629. {
  630. status = move_recs_r(ncp, ncp->old);
  631. if(status != NC_NOERR)
  632. return status;
  633. if(ncp->begin_var > ncp->old->begin_var)
  634. {
  635. status = move_vars_r(ncp, ncp->old);
  636. if(status != NC_NOERR)
  637. return status;
  638. }
  639. /* else if (ncp->begin_var == ncp->old->begin_var) { NOOP } */
  640. }
  641. else
  642. { /* Even if (ncp->begin_rec == ncp->old->begin_rec)
  643. and (ncp->begin_var == ncp->old->begin_var)
  644. might still have added a new record variable */
  645. if(ncp->recsize > ncp->old->recsize)
  646. {
  647. status = move_recs_r(ncp, ncp->old);
  648. if(status != NC_NOERR)
  649. return status;
  650. }
  651. }
  652. }
  653. }
  654. status = write_NC(ncp);
  655. if(status != NC_NOERR)
  656. return status;
  657. if(NC_dofill(ncp))
  658. {
  659. if(NC_IsNew(ncp))
  660. {
  661. status = fillerup(ncp);
  662. if(status != NC_NOERR)
  663. return status;
  664. }
  665. else if(ncp->vars.nelems > ncp->old->vars.nelems)
  666. {
  667. status = fill_added(ncp, ncp->old);
  668. if(status != NC_NOERR)
  669. return status;
  670. status = fill_added_recs(ncp, ncp->old);
  671. if(status != NC_NOERR)
  672. return status;
  673. }
  674. }
  675. if(ncp->old != NULL)
  676. {
  677. free_NC(ncp->old);
  678. ncp->old = NULL;
  679. }
  680. fClr(ncp->flags, NC_CREAT | NC_INDEF);
  681. return ncio_sync(ncp->nciop);
  682. }
  683. #ifdef LOCKNUMREC
  684. static int
  685. NC_init_pe(NC *ncp, int basepe) {
  686. if (basepe < 0 || basepe >= _num_pes()) {
  687. return NC_EINVAL; /* invalid base pe */
  688. }
  689. /* initialize common values */
  690. ncp->lock[LOCKNUMREC_VALUE] = 0;
  691. ncp->lock[LOCKNUMREC_LOCK] = 0;
  692. ncp->lock[LOCKNUMREC_SERVING] = 0;
  693. ncp->lock[LOCKNUMREC_BASEPE] = basepe;
  694. return NC_NOERR;
  695. }
  696. #endif
  697. /*
  698. * Compute the expected size of the file.
  699. */
  700. int
  701. NC_calcsize(const NC *ncp, off_t *calcsizep)
  702. {
  703. NC_var **vpp = (NC_var **)ncp->vars.value;
  704. NC_var *const *const end = &vpp[ncp->vars.nelems];
  705. NC_var *last_fix = NULL; /* last "non-record" var */
  706. int numrecvars = 0; /* number of record variables */
  707. if(ncp->vars.nelems == 0) { /* no non-record variables and
  708. no record variables */
  709. *calcsizep = ncp->xsz; /* size of header */
  710. return NC_NOERR;
  711. }
  712. for( /*NADA*/; vpp < end; vpp++) {
  713. if(IS_RECVAR(*vpp)) {
  714. numrecvars++;
  715. } else {
  716. last_fix = *vpp;
  717. }
  718. }
  719. if(numrecvars == 0) {
  720. off_t varsize;
  721. assert(last_fix != NULL);
  722. varsize = last_fix->len;
  723. if(last_fix->len == X_UINT_MAX) { /* huge last fixed var */
  724. int i;
  725. varsize = 1;
  726. for(i = 0; i < last_fix->ndims; i++ ) {
  727. varsize *= last_fix->shape[i];
  728. }
  729. }
  730. *calcsizep = last_fix->begin + varsize;
  731. /*last_var = last_fix;*/
  732. } else { /* we have at least one record variable */
  733. *calcsizep = ncp->begin_rec + ncp->numrecs * ncp->recsize;
  734. }
  735. return NC_NOERR;
  736. }
  737. /* Public */
  738. int NC3_new_nc(NC** ncpp)
  739. {
  740. NC *ncp;
  741. #if _CRAYMPP && defined(LOCKNUMREC)
  742. ncp = (NC *) shmalloc(sizeof(NC));
  743. #else
  744. ncp = (NC *) malloc(sizeof(NC));
  745. #endif /* _CRAYMPP && LOCKNUMREC */
  746. if(ncp == NULL)
  747. return NC_ENOMEM;
  748. (void) memset(ncp, 0, sizeof(NC));
  749. ncp->xsz = MIN_NC_XSZ;
  750. assert(ncp->xsz == ncx_len_NC(ncp,0));
  751. if(ncpp) *ncpp = ncp;
  752. return NC_NOERR;
  753. }
  754. /* WARNING: SIGNATURE CHANGE */
  755. int
  756. NC3_create(const char *path, int ioflags,
  757. size_t initialsz, int basepe,
  758. size_t *chunksizehintp,
  759. int use_parallel, void* parameters,
  760. NC_Dispatch* dispatch, NC** ncpp)
  761. {
  762. NC *ncp;
  763. int status;
  764. void *xp = NULL;
  765. int sizeof_off_t = 0;
  766. #if ALWAYS_NC_SHARE /* DEBUG */
  767. fSet(ioflags, NC_SHARE);
  768. #endif
  769. ncp = new_NC(chunksizehintp,dispatch);
  770. if(ncp == NULL)
  771. return NC_ENOMEM;
  772. #if defined(LOCKNUMREC) /* && _CRAYMPP */
  773. if (status = NC_init_pe(ncp, basepe)) {
  774. return status;
  775. }
  776. #else
  777. /*
  778. * !_CRAYMPP, only pe 0 is valid
  779. */
  780. if(basepe != 0)
  781. return NC_EINVAL;
  782. #endif
  783. assert(ncp->flags == 0);
  784. /* Apply default create format. */
  785. if (default_create_format == NC_FORMAT_64BIT)
  786. ioflags |= NC_64BIT_OFFSET;
  787. if (fIsSet(ioflags, NC_64BIT_OFFSET)) {
  788. fSet(ncp->flags, NC_64BIT_OFFSET);
  789. sizeof_off_t = 8;
  790. } else {
  791. sizeof_off_t = 4;
  792. }
  793. assert(ncp->xsz == ncx_len_NC(ncp,sizeof_off_t));
  794. status = ncio_create(path, ioflags, initialsz,
  795. 0, ncp->xsz, &ncp->chunk,
  796. &ncp->nciop, &xp);
  797. if(status != NC_NOERR)
  798. {
  799. /* translate error status */
  800. if(status == EEXIST)
  801. status = NC_EEXIST;
  802. goto unwind_alloc;
  803. }
  804. fSet(ncp->flags, NC_CREAT);
  805. if(fIsSet(ncp->nciop->ioflags, NC_SHARE))
  806. {
  807. /*
  808. * NC_SHARE implies sync up the number of records as well.
  809. * (File format version one.)
  810. * Note that other header changes are not shared
  811. * automatically. Some sort of IPC (external to this package)
  812. * would be used to trigger a call to nc_sync().
  813. */
  814. fSet(ncp->flags, NC_NSYNC);
  815. }
  816. status = ncx_put_NC(ncp, &xp, sizeof_off_t, ncp->xsz);
  817. if(status != NC_NOERR)
  818. goto unwind_ioc;
  819. add_to_NCList(ncp);
  820. if(chunksizehintp != NULL)
  821. *chunksizehintp = ncp->chunk;
  822. ncp->int_ncid = ncp->nciop->fd;
  823. if(ncpp) *ncpp = ncp;
  824. return NC_NOERR;
  825. unwind_ioc:
  826. (void) ncio_close(ncp->nciop, 1); /* N.B.: unlink */
  827. ncp->nciop = NULL;
  828. /*FALLTHRU*/
  829. unwind_alloc:
  830. free_NC(ncp);
  831. return status;
  832. }
  833. /* This function sets a default create flag that will be logically
  834. or'd to whatever flags are passed into nc_create for all future
  835. calls to nc_create.
  836. Valid default create flags are NC_64BIT_OFFSET, NC_CLOBBER,
  837. NC_LOCK, NC_SHARE. */
  838. int
  839. nc_set_default_format(int format, int *old_formatp)
  840. {
  841. /* Return existing format if desired. */
  842. if (old_formatp)
  843. *old_formatp = default_create_format;
  844. /* Make sure only valid format is set. */
  845. #ifdef USE_NETCDF4
  846. if (format != NC_FORMAT_CLASSIC && format != NC_FORMAT_64BIT &&
  847. format != NC_FORMAT_NETCDF4 && format != NC_FORMAT_NETCDF4_CLASSIC)
  848. return NC_EINVAL;
  849. #else
  850. if (format != NC_FORMAT_CLASSIC && format != NC_FORMAT_64BIT)
  851. return NC_EINVAL;
  852. #endif
  853. default_create_format = format;
  854. return NC_NOERR;
  855. }
  856. int
  857. NC3_open(const char * path, int ioflags,
  858. int basepe, size_t *chunksizehintp,
  859. int use_parallel,void* parameters,
  860. NC_Dispatch* dispatch, NC** ncpp)
  861. {
  862. NC *ncp;
  863. int status;
  864. #if ALWAYS_NC_SHARE /* DEBUG */
  865. fSet(ioflags, NC_SHARE);
  866. #endif
  867. ncp = new_NC(chunksizehintp,dispatch);
  868. if(ncp == NULL)
  869. return NC_ENOMEM;
  870. #if defined(LOCKNUMREC) /* && _CRAYMPP */
  871. if (status = NC_init_pe(ncp, basepe)) {
  872. return status;
  873. }
  874. #else
  875. /*
  876. * !_CRAYMPP, only pe 0 is valid
  877. */
  878. if(basepe != 0)
  879. return NC_EINVAL;
  880. #endif
  881. status = ncio_open(path, ioflags, 0, 0, &ncp->chunk, &ncp->nciop, 0);
  882. if(status)
  883. goto unwind_alloc;
  884. assert(ncp->flags == 0);
  885. if(fIsSet(ncp->nciop->ioflags, NC_SHARE))
  886. {
  887. /*
  888. * NC_SHARE implies sync up the number of records as well.
  889. * (File format version one.)
  890. * Note that other header changes are not shared
  891. * automatically. Some sort of IPC (external to this package)
  892. * would be used to trigger a call to nc_sync().
  893. */
  894. fSet(ncp->flags, NC_NSYNC);
  895. }
  896. status = nc_get_NC(ncp);
  897. if(status != NC_NOERR)
  898. goto unwind_ioc;
  899. add_to_NCList(ncp);
  900. if(chunksizehintp != NULL)
  901. *chunksizehintp = ncp->chunk;
  902. ncp->int_ncid = ncp->nciop->fd;
  903. if(ncpp) *ncpp = ncp;
  904. return NC_NOERR;
  905. unwind_ioc:
  906. (void) ncio_close(ncp->nciop, 0);
  907. ncp->nciop = NULL;
  908. /*FALLTHRU*/
  909. unwind_alloc:
  910. free_NC(ncp);
  911. return status;
  912. }
  913. int
  914. NC3__enddef(int ncid,
  915. size_t h_minfree, size_t v_align,
  916. size_t v_minfree, size_t r_align)
  917. {
  918. int status;
  919. NC *ncp;
  920. status = NC_check_id(ncid, &ncp);
  921. if(status != NC_NOERR)
  922. return status;
  923. if(!NC_indef(ncp))
  924. return(NC_ENOTINDEFINE);
  925. return (NC_endef(ncp, h_minfree, v_align, v_minfree, r_align));
  926. }
  927. int
  928. NC3_close(int ncid)
  929. {
  930. int status = NC_NOERR;
  931. NC *ncp;
  932. status = NC_check_id(ncid, &ncp);
  933. if(status != NC_NOERR)
  934. return status;
  935. if(NC_indef(ncp))
  936. {
  937. status = NC_endef(ncp, 0, 1, 0, 1); /* TODO: defaults */
  938. if(status != NC_NOERR )
  939. {
  940. (void) nc_abort(ncid);
  941. return status;
  942. }
  943. }
  944. else if(!NC_readonly(ncp))
  945. {
  946. status = NC_sync(ncp);
  947. /* flush buffers before any filesize comparisons */
  948. (void) ncio_sync(ncp->nciop);
  949. }
  950. /*
  951. * If file opened for writing and filesize is less than
  952. * what it should be (due to previous use of NOFILL mode),
  953. * pad it to correct size, as reported by NC_calcsize().
  954. */
  955. if (status == ENOERR) {
  956. off_t filesize; /* current size of open file */
  957. off_t calcsize; /* calculated file size, from header */
  958. status = ncio_filesize(ncp->nciop, &filesize);
  959. if(status != ENOERR)
  960. return status;
  961. status = NC_calcsize(ncp, &calcsize);
  962. if(status != NC_NOERR)
  963. return status;
  964. if(filesize < calcsize && !NC_readonly(ncp)) {
  965. status = ncio_pad_length(ncp->nciop, calcsize);
  966. if(status != ENOERR)
  967. return status;
  968. }
  969. }
  970. (void) ncio_close(ncp->nciop, 0);
  971. ncp->nciop = NULL;
  972. del_from_NCList(ncp);
  973. free_NC(ncp);
  974. return status;
  975. }
  976. /*
  977. * In data mode, same as ncclose.
  978. * In define mode, restore previous definition.
  979. * In create, remove the file.
  980. */
  981. int
  982. NC3_abort(int ncid)
  983. {
  984. int status;
  985. NC *ncp;
  986. int doUnlink = 0;
  987. status = NC_check_id(ncid, &ncp);
  988. if(status != NC_NOERR)
  989. return status;
  990. doUnlink = NC_IsNew(ncp);
  991. if(ncp->old != NULL)
  992. {
  993. /* a plain redef, not a create */
  994. assert(!NC_IsNew(ncp));
  995. assert(fIsSet(ncp->flags, NC_INDEF));
  996. free_NC(ncp->old);
  997. ncp->old = NULL;
  998. fClr(ncp->flags, NC_INDEF);
  999. }
  1000. else if(!NC_readonly(ncp))
  1001. {
  1002. status = NC_sync(ncp);
  1003. if(status != NC_NOERR)
  1004. return status;
  1005. }
  1006. (void) ncio_close(ncp->nciop, doUnlink);
  1007. ncp->nciop = NULL;
  1008. del_from_NCList(ncp);
  1009. free_NC(ncp);
  1010. return NC_NOERR;
  1011. }
  1012. int
  1013. NC3_redef(int ncid)
  1014. {
  1015. int status;
  1016. NC *ncp;
  1017. status = NC_check_id(ncid, &ncp);
  1018. if(status != NC_NOERR)
  1019. return status;
  1020. if(NC_readonly(ncp))
  1021. return NC_EPERM;
  1022. if(NC_indef(ncp))
  1023. return NC_EINDEFINE;
  1024. if(fIsSet(ncp->nciop->ioflags, NC_SHARE))
  1025. {
  1026. /* read in from disk */
  1027. status = read_NC(ncp);
  1028. if(status != NC_NOERR)
  1029. return status;
  1030. }
  1031. ncp->old = dup_NC(ncp);
  1032. if(ncp->old == NULL)
  1033. return NC_ENOMEM;
  1034. fSet(ncp->flags, NC_INDEF);
  1035. return NC_NOERR;
  1036. }
  1037. int
  1038. NC3_inq(int ncid,
  1039. int *ndimsp,
  1040. int *nvarsp,
  1041. int *nattsp,
  1042. int *xtendimp)
  1043. {
  1044. int status;
  1045. NC *ncp;
  1046. status = NC_check_id(ncid, &ncp);
  1047. if(status != NC_NOERR)
  1048. return status;
  1049. if(ndimsp != NULL)
  1050. *ndimsp = (int) ncp->dims.nelems;
  1051. if(nvarsp != NULL)
  1052. *nvarsp = (int) ncp->vars.nelems;
  1053. if(nattsp != NULL)
  1054. *nattsp = (int) ncp->attrs.nelems;
  1055. if(xtendimp != NULL)
  1056. *xtendimp = find_NC_Udim(&ncp->dims, NULL);
  1057. return NC_NOERR;
  1058. }
  1059. int
  1060. NC3_inq_unlimdim(int ncid, int *xtendimp)
  1061. {
  1062. int status;
  1063. NC *ncp;
  1064. status = NC_check_id(ncid, &ncp);
  1065. if(status != NC_NOERR)
  1066. return status;
  1067. if(xtendimp != NULL)
  1068. *xtendimp = find_NC_Udim(&ncp->dims, NULL);
  1069. return NC_NOERR;
  1070. }
  1071. int
  1072. NC3_sync(int ncid)
  1073. {
  1074. int status;
  1075. NC *ncp;
  1076. status = NC_check_id(ncid, &ncp);
  1077. if(status != NC_NOERR)
  1078. return status;
  1079. if(NC_indef(ncp))
  1080. return NC_EINDEFINE;
  1081. if(NC_readonly(ncp))
  1082. {
  1083. return read_NC(ncp);
  1084. }
  1085. /* else, read/write */
  1086. status = NC_sync(ncp);
  1087. if(status != NC_NOERR)
  1088. return status;
  1089. status = ncio_sync(ncp->nciop);
  1090. if(status != NC_NOERR)
  1091. return status;
  1092. #ifdef USE_FSYNC
  1093. /* may improve concurrent access, but slows performance if
  1094. * called frequently */
  1095. #ifndef WIN32
  1096. status = fsync(ncp->nciop->fd);
  1097. #else
  1098. status = _commit(ncp->nciop->fd);
  1099. #endif /* WIN32 */
  1100. #endif /* USE_FSYNC */
  1101. return status;
  1102. }
  1103. int
  1104. NC3_set_fill(int ncid,
  1105. int fillmode, int *old_mode_ptr)
  1106. {
  1107. int status;
  1108. NC *ncp;
  1109. int oldmode;
  1110. status = NC_check_id(ncid, &ncp);
  1111. if(status != NC_NOERR)
  1112. return status;
  1113. if(NC_readonly(ncp))
  1114. return NC_EPERM;
  1115. oldmode = fIsSet(ncp->flags, NC_NOFILL) ? NC_NOFILL : NC_FILL;
  1116. if(fillmode == NC_NOFILL)
  1117. {
  1118. fSet(ncp->flags, NC_NOFILL);
  1119. }
  1120. else if(fillmode == NC_FILL)
  1121. {
  1122. if(fIsSet(ncp->flags, NC_NOFILL))
  1123. {
  1124. /*
  1125. * We are changing back to fill mode
  1126. * so do a sync
  1127. */
  1128. status = NC_sync(ncp);
  1129. if(status != NC_NOERR)
  1130. return status;
  1131. }
  1132. fClr(ncp->flags, NC_NOFILL);
  1133. }
  1134. else
  1135. {
  1136. return NC_EINVAL; /* Invalid fillmode */
  1137. }
  1138. if(old_mode_ptr != NULL)
  1139. *old_mode_ptr = oldmode;
  1140. return NC_NOERR;
  1141. }
  1142. #ifdef LOCKNUMREC
  1143. /* create function versions of the NC_*_numrecs macros */
  1144. size_t
  1145. NC_get_numrecs(const NC *ncp) {
  1146. shmem_t numrec;
  1147. shmem_short_get(&numrec, (shmem_t *) ncp->lock + LOCKNUMREC_VALUE, 1,
  1148. ncp->lock[LOCKNUMREC_BASEPE]);
  1149. return (size_t) numrec;
  1150. }
  1151. void
  1152. NC_set_numrecs(NC *ncp, size_t nrecs)
  1153. {
  1154. shmem_t numrec = (shmem_t) nrecs;
  1155. /* update local value too */
  1156. ncp->lock[LOCKNUMREC_VALUE] = (ushmem_t) numrec;
  1157. shmem_short_put((shmem_t *) ncp->lock + LOCKNUMREC_VALUE, &numrec, 1,
  1158. ncp->lock[LOCKNUMREC_BASEPE]);
  1159. }
  1160. void NC_increase_numrecs(NC *ncp, size_t nrecs)
  1161. {
  1162. /* this is only called in one place that's already protected
  1163. * by a lock ... so don't worry about it */
  1164. if (nrecs > NC_get_numrecs(ncp))
  1165. NC_set_numrecs(ncp, nrecs);
  1166. }
  1167. #endif /* LOCKNUMREC */
  1168. /* everyone in communicator group will be executing this */
  1169. /*ARGSUSED*/
  1170. int
  1171. NC3_set_base_pe(int ncid, int pe)
  1172. {
  1173. #if _CRAYMPP && defined(LOCKNUMREC)
  1174. int status;
  1175. NC *ncp;
  1176. shmem_t numrecs;
  1177. if ((status = NC_check_id(ncid, &ncp)) != NC_NOERR) {
  1178. return status;
  1179. }
  1180. if (pe < 0 || pe >= _num_pes()) {
  1181. return NC_EINVAL; /* invalid base pe */
  1182. }
  1183. numrecs = (shmem_t) NC_get_numrecs(ncp);
  1184. ncp->lock[LOCKNUMREC_VALUE] = (ushmem_t) numrecs;
  1185. /* update serving & lock values for a "smooth" transition */
  1186. /* note that the "real" server will being doing this as well */
  1187. /* as all the rest in the group */
  1188. /* must have syncronization before & after this step */
  1189. shmem_short_get(
  1190. (shmem_t *) ncp->lock + LOCKNUMREC_SERVING,
  1191. (shmem_t *) ncp->lock + LOCKNUMREC_SERVING,
  1192. 1, ncp->lock[LOCKNUMREC_BASEPE]);
  1193. shmem_short_get(
  1194. (shmem_t *) ncp->lock + LOCKNUMREC_LOCK,
  1195. (shmem_t *) ncp->lock + LOCKNUMREC_LOCK,
  1196. 1, ncp->lock[LOCKNUMREC_BASEPE]);
  1197. /* complete transition */
  1198. ncp->lock[LOCKNUMREC_BASEPE] = (ushmem_t) pe;
  1199. #endif /* _CRAYMPP && LOCKNUMREC */
  1200. return NC_NOERR;
  1201. }
  1202. /*ARGSUSED*/
  1203. int
  1204. NC3_inq_base_pe(int ncid, int *pe)
  1205. {
  1206. #if _CRAYMPP && defined(LOCKNUMREC)
  1207. int status;
  1208. NC *ncp;
  1209. if ((status = NC_check_id(ncid, &ncp)) != NC_NOERR) {
  1210. return status;
  1211. }
  1212. *pe = (int) ncp->lock[LOCKNUMREC_BASEPE];
  1213. #else
  1214. /*
  1215. * !_CRAYMPP, only pe 0 is valid
  1216. */
  1217. *pe = 0;
  1218. #endif /* _CRAYMPP && LOCKNUMREC */
  1219. return NC_NOERR;
  1220. }
  1221. int
  1222. NC3_inq_format(int ncid, int *formatp)
  1223. {
  1224. int status;
  1225. NC *ncp;
  1226. status = NC_check_id(ncid, &ncp);
  1227. if(status != NC_NOERR)
  1228. return status;
  1229. /* only need to check for netCDF-3 variants, since this is never called for netCDF-4
  1230. files */
  1231. *formatp = fIsSet(ncp->flags, NC_64BIT_OFFSET) ? NC_FORMAT_64BIT
  1232. : NC_FORMAT_CLASSIC;
  1233. return NC_NOERR;
  1234. }
  1235. /* The sizes of types may vary from platform to platform, but within
  1236. * netCDF files, type sizes are fixed. */
  1237. #define NC_BYTE_LEN 1
  1238. #define NC_CHAR_LEN 1
  1239. #define NC_SHORT_LEN 2
  1240. #define NC_INT_LEN 4
  1241. #define NC_FLOAT_LEN 4
  1242. #define NC_DOUBLE_LEN 8
  1243. #define NUM_ATOMIC_TYPES 6
  1244. /* This netCDF-4 function proved so popular that a netCDF-classic
  1245. * version is provided. You're welcome. */
  1246. int
  1247. NC3_inq_type(int ncid, nc_type typeid, char *name, size_t *size)
  1248. {
  1249. int atomic_size[NUM_ATOMIC_TYPES] = {NC_BYTE_LEN, NC_CHAR_LEN, NC_SHORT_LEN,
  1250. NC_INT_LEN, NC_FLOAT_LEN, NC_DOUBLE_LEN};
  1251. char atomic_name[NUM_ATOMIC_TYPES][NC_MAX_NAME + 1] = {"byte", "char", "short",
  1252. "int", "float", "double"};
  1253. /* Only netCDF classic model needs to be handled. */
  1254. if (typeid < NC_BYTE || typeid > NC_DOUBLE)
  1255. return NC_EBADTYPE;
  1256. /* Give the user the values they want. Subtract one because types
  1257. * are numbered starting at 1, not 0. */
  1258. if (name)
  1259. strcpy(name, atomic_name[typeid - 1]);
  1260. if (size)
  1261. *size = atomic_size[typeid - 1];
  1262. return NC_NOERR;
  1263. }
  1264. int
  1265. nc_delete_mp(const char * path, int basepe)
  1266. {
  1267. NC *ncp;
  1268. int status;
  1269. size_t chunk = 512;
  1270. status = NC3_new_nc(&ncp);
  1271. if(status) return status;
  1272. ncp->chunk = chunk;
  1273. #if defined(LOCKNUMREC) /* && _CRAYMPP */
  1274. if (status = NC_init_pe(ncp, basepe)) {
  1275. return status;
  1276. }
  1277. #else
  1278. /*
  1279. * !_CRAYMPP, only pe 0 is valid
  1280. */
  1281. if(basepe != 0)
  1282. return NC_EINVAL;
  1283. #endif
  1284. status = ncio_open(path, NC_NOWRITE,
  1285. 0, 0, &ncp->chunk,
  1286. &ncp->nciop, 0);
  1287. if(status)
  1288. goto unwind_alloc;
  1289. assert(ncp->flags == 0);
  1290. status = nc_get_NC(ncp);
  1291. if(status != NC_NOERR)
  1292. {
  1293. /* Not a netcdf file, don't delete */
  1294. /* ??? is this the right semantic? what if it was just too big? */
  1295. (void) ncio_close(ncp->nciop, 0);
  1296. }
  1297. else
  1298. {
  1299. /* ncio_close does the unlink */
  1300. status = ncio_close(ncp->nciop, 1); /* ncio_close does the unlink */
  1301. }
  1302. ncp->nciop = NULL;
  1303. ncp->nciop = NULL;
  1304. unwind_alloc:
  1305. free_NC(ncp);
  1306. return status;
  1307. }
  1308. int
  1309. nc_delete(const char * path)
  1310. {
  1311. return nc_delete_mp(path, 0);
  1312. }