00001
00002
00003
00004
00005
00006
00007 #include "nc.h"
00008 #include "rnd.h"
00009 #include <stdlib.h>
00010 #include <string.h>
00011 #include <assert.h>
00012 #include "ncx.h"
00013 #if defined(LOCKNUMREC)
00014 # include <mpp/shmem.h>
00015 # include <intrinsics.h>
00016 #endif
00017
00018
00019 static NC *NClist = NULL;
00020
00021
00022 int default_create_format = NC_FORMAT_CLASSIC;
00023
00024
00025 #define MAGIC_NUM_LEN 4
00026 #define VER_CLASSIC 1
00027 #define VER_64BIT_OFFSET 2
00028 #define VER_HDF5 3
00029
00030 static void
00031 add_to_NCList(NC *ncp)
00032 {
00033 assert(ncp != NULL);
00034
00035 ncp->prev = NULL;
00036 if(NClist != NULL)
00037 NClist->prev = ncp;
00038 ncp->next = NClist;
00039 NClist = ncp;
00040 }
00041
00042 static void
00043 del_from_NCList(NC *ncp)
00044 {
00045 assert(ncp != NULL);
00046
00047 if(NClist == ncp)
00048 {
00049 assert(ncp->prev == NULL);
00050 NClist = ncp->next;
00051 }
00052 else
00053 {
00054 assert(ncp->prev != NULL);
00055 ncp->prev->next = ncp->next;
00056 }
00057
00058 if(ncp->next != NULL)
00059 ncp->next->prev = ncp->prev;
00060
00061 ncp->next = NULL;
00062 ncp->prev = NULL;
00063 }
00064
00065
00066 int
00067 NC_check_id(int ncid, NC **ncpp)
00068 {
00069 NC *ncp;
00070
00071 if(ncid >= 0)
00072 {
00073 for(ncp = NClist; ncp != NULL; ncp = ncp->next)
00074 {
00075 if(ncp->nciop->fd == ncid)
00076 {
00077 *ncpp = ncp;
00078 return NC_NOERR;
00079 }
00080 }
00081 }
00082
00083
00084 return NC_EBADID;
00085 }
00086
00087
00088 static void
00089 free_NC(NC *ncp)
00090 {
00091 if(ncp == NULL)
00092 return;
00093 free_NC_dimarrayV(&ncp->dims);
00094 free_NC_attrarrayV(&ncp->attrs);
00095 free_NC_vararrayV(&ncp->vars);
00096 #if _CRAYMPP && defined(LOCKNUMREC)
00097 shfree(ncp);
00098 #else
00099 free(ncp);
00100 #endif
00101 }
00102
00103
00104 static NC *
00105 new_NC(const size_t *chunkp)
00106 {
00107 NC *ncp;
00108
00109 #if _CRAYMPP && defined(LOCKNUMREC)
00110 ncp = (NC *) shmalloc(sizeof(NC));
00111 #else
00112 ncp = (NC *) malloc(sizeof(NC));
00113 #endif
00114 if(ncp == NULL)
00115 return NULL;
00116 (void) memset(ncp, 0, sizeof(NC));
00117
00118 ncp->xsz = MIN_NC_XSZ;
00119 assert(ncp->xsz == ncx_len_NC(ncp,0));
00120
00121 ncp->chunk = chunkp != NULL ? *chunkp : NC_SIZEHINT_DEFAULT;
00122
00123 return ncp;
00124 }
00125
00126
00127 static NC *
00128 dup_NC(const NC *ref)
00129 {
00130 NC *ncp;
00131
00132 #if _CRAYMPP && defined(LOCKNUMREC)
00133 ncp = (NC *) shmalloc(sizeof(NC));
00134 #else
00135 ncp = (NC *) malloc(sizeof(NC));
00136 #endif
00137 if(ncp == NULL)
00138 return NULL;
00139 (void) memset(ncp, 0, sizeof(NC));
00140
00141 if(dup_NC_dimarrayV(&ncp->dims, &ref->dims) != NC_NOERR)
00142 goto err;
00143 if(dup_NC_attrarrayV(&ncp->attrs, &ref->attrs) != NC_NOERR)
00144 goto err;
00145 if(dup_NC_vararrayV(&ncp->vars, &ref->vars) != NC_NOERR)
00146 goto err;
00147
00148 ncp->xsz = ref->xsz;
00149 ncp->begin_var = ref->begin_var;
00150 ncp->begin_rec = ref->begin_rec;
00151 ncp->recsize = ref->recsize;
00152 NC_set_numrecs(ncp, NC_get_numrecs(ref));
00153 return ncp;
00154 err:
00155 free_NC(ncp);
00156 return NULL;
00157 }
00158
00159
00160
00161
00162
00163
00164
00165
00166 int
00167 nc_cktype(nc_type type)
00168 {
00169 switch((int)type){
00170 case NC_BYTE:
00171 case NC_CHAR:
00172 case NC_SHORT:
00173 case NC_INT:
00174 case NC_FLOAT:
00175 case NC_DOUBLE:
00176 return(NC_NOERR);
00177 }
00178 return(NC_EBADTYPE);
00179 }
00180
00181
00182
00183
00184
00185
00186 size_t
00187 ncx_howmany(nc_type type, size_t xbufsize)
00188 {
00189 switch(type){
00190 case NC_BYTE:
00191 case NC_CHAR:
00192 return xbufsize;
00193 case NC_SHORT:
00194 return xbufsize/X_SIZEOF_SHORT;
00195 case NC_INT:
00196 return xbufsize/X_SIZEOF_INT;
00197 case NC_FLOAT:
00198 return xbufsize/X_SIZEOF_FLOAT;
00199 case NC_DOUBLE:
00200 return xbufsize/X_SIZEOF_DOUBLE;
00201 }
00202 assert("ncx_howmany: Bad type" == 0);
00203 return(0);
00204 }
00205
00206 #define D_RNDUP(x, align) _RNDUP(x, (off_t)(align))
00207
00208
00209
00210
00211
00212 static int
00213 NC_begins(NC *ncp,
00214 size_t h_minfree, size_t v_align,
00215 size_t v_minfree, size_t r_align)
00216 {
00217 size_t ii;
00218 int sizeof_off_t;
00219 off_t index = 0;
00220 NC_var **vpp;
00221 NC_var *last = NULL;
00222
00223 if(v_align == NC_ALIGN_CHUNK)
00224 v_align = ncp->chunk;
00225 if(r_align == NC_ALIGN_CHUNK)
00226 r_align = ncp->chunk;
00227
00228 if (fIsSet(ncp->flags, NC_64BIT_OFFSET)) {
00229 sizeof_off_t = 8;
00230 } else {
00231 sizeof_off_t = 4;
00232 }
00233
00234 ncp->xsz = ncx_len_NC(ncp,sizeof_off_t);
00235
00236 if(ncp->vars.nelems == 0)
00237 return NC_NOERR;
00238
00239
00240
00241 if (ncp->begin_var < ncp->xsz + h_minfree ||
00242 ncp->begin_var != D_RNDUP(ncp->begin_var, v_align) )
00243 {
00244 index = (off_t) ncp->xsz;
00245 ncp->begin_var = D_RNDUP(index, v_align);
00246 if(ncp->begin_var < index + h_minfree)
00247 {
00248 ncp->begin_var = D_RNDUP(index + (off_t)h_minfree, v_align);
00249 }
00250 }
00251 index = ncp->begin_var;
00252
00253
00254 vpp = ncp->vars.value;
00255 for(ii = 0; ii < ncp->vars.nelems ; ii++, vpp++)
00256 {
00257 if( IS_RECVAR(*vpp) )
00258 {
00259
00260 continue;
00261 }
00262 #if 0
00263 fprintf(stderr, " VAR %d %s: %ld\n", ii, (*vpp)->name->cp, (long)index);
00264 #endif
00265 if( sizeof_off_t == 4 && (index > X_OFF_MAX || index < 0) )
00266 {
00267 return NC_EVARSIZE;
00268 }
00269 (*vpp)->begin = index;
00270 index += (*vpp)->len;
00271 }
00272
00273
00274
00275
00276 if (ncp->begin_rec < index + v_minfree ||
00277 ncp->begin_rec != D_RNDUP(ncp->begin_rec, r_align) )
00278 {
00279 ncp->begin_rec = D_RNDUP(index, r_align);
00280 if(ncp->begin_rec < index + v_minfree)
00281 {
00282 ncp->begin_rec = D_RNDUP(index + (off_t)v_minfree, r_align);
00283 }
00284 }
00285 index = ncp->begin_rec;
00286
00287 ncp->recsize = 0;
00288
00289
00290 vpp = (NC_var **)ncp->vars.value;
00291 for(ii = 0; ii < ncp->vars.nelems; ii++, vpp++)
00292 {
00293 if( !IS_RECVAR(*vpp) )
00294 {
00295
00296 continue;
00297 }
00298
00299 #if 0
00300 fprintf(stderr, " REC %d %s: %ld\n", ii, (*vpp)->name->cp, (long)index);
00301 #endif
00302 if( sizeof_off_t == 4 && (index > X_OFF_MAX || index < 0) )
00303 {
00304 return NC_EVARSIZE;
00305 }
00306 (*vpp)->begin = index;
00307 index += (*vpp)->len;
00308
00309 #if SIZEOF_OFF_T == SIZEOF_SIZE_T && SIZEOF_SIZE_T == 4
00310 if( ncp->recsize > X_UINT_MAX - (*vpp)->len )
00311 {
00312 return NC_EVARSIZE;
00313 }
00314 #endif
00315 ncp->recsize += (*vpp)->len;
00316 last = (*vpp);
00317 }
00318
00319
00320
00321
00322 if(last != NULL && ncp->recsize == last->len)
00323 ncp->recsize = *last->dsizes * last->xsz;
00324
00325 if(NC_IsNew(ncp))
00326 NC_set_numrecs(ncp, 0);
00327 return NC_NOERR;
00328 }
00329
00330
00331
00332
00333
00334
00335 int
00336 read_numrecs(NC *ncp)
00337 {
00338 int status = NC_NOERR;
00339 const void *xp = NULL;
00340 size_t nrecs = NC_get_numrecs(ncp);
00341
00342 assert(!NC_indef(ncp));
00343
00344 #define NC_NUMRECS_OFFSET 4
00345 #define NC_NUMRECS_EXTENT 4
00346 status = ncp->nciop->get(ncp->nciop,
00347 NC_NUMRECS_OFFSET, NC_NUMRECS_EXTENT, 0, (void **)&xp);
00348
00349 if(status != NC_NOERR)
00350 return status;
00351
00352 status = ncx_get_size_t(&xp, &nrecs);
00353
00354 (void) ncp->nciop->rel(ncp->nciop, NC_NUMRECS_OFFSET, 0);
00355
00356 if(status == NC_NOERR)
00357 {
00358 NC_set_numrecs(ncp, nrecs);
00359 fClr(ncp->flags, NC_NDIRTY);
00360 }
00361
00362 return status;
00363 }
00364
00365
00366
00367
00368
00369
00370 int
00371 write_numrecs(NC *ncp)
00372 {
00373 int status = NC_NOERR;
00374 void *xp = NULL;
00375
00376 assert(!NC_readonly(ncp));
00377 assert(!NC_indef(ncp));
00378
00379 status = ncp->nciop->get(ncp->nciop,
00380 NC_NUMRECS_OFFSET, NC_NUMRECS_EXTENT, RGN_WRITE, &xp);
00381 if(status != NC_NOERR)
00382 return status;
00383
00384 {
00385 const size_t nrecs = NC_get_numrecs(ncp);
00386 status = ncx_put_size_t(&xp, &nrecs);
00387 }
00388
00389 (void) ncp->nciop->rel(ncp->nciop, NC_NUMRECS_OFFSET, RGN_MODIFIED);
00390
00391 if(status == NC_NOERR)
00392 fClr(ncp->flags, NC_NDIRTY);
00393
00394 return status;
00395 }
00396
00397
00398
00399
00400
00401
00402 static int
00403 read_NC(NC *ncp)
00404 {
00405 int status = NC_NOERR;
00406
00407 free_NC_dimarrayV(&ncp->dims);
00408 free_NC_attrarrayV(&ncp->attrs);
00409 free_NC_vararrayV(&ncp->vars);
00410
00411 status = nc_get_NC(ncp);
00412
00413 if(status == NC_NOERR)
00414 fClr(ncp->flags, NC_NDIRTY | NC_HDIRTY);
00415
00416 return status;
00417 }
00418
00419
00420
00421
00422
00423 static int
00424 write_NC(NC *ncp)
00425 {
00426 int status = NC_NOERR;
00427
00428 assert(!NC_readonly(ncp));
00429
00430 status = ncx_put_NC(ncp, NULL, 0, 0);
00431
00432 if(status == NC_NOERR)
00433 fClr(ncp->flags, NC_NDIRTY | NC_HDIRTY);
00434
00435 return status;
00436 }
00437
00438
00439
00440
00441
00442 int
00443 NC_sync(NC *ncp)
00444 {
00445 assert(!NC_readonly(ncp));
00446
00447 if(NC_hdirty(ncp))
00448 {
00449 return write_NC(ncp);
00450 }
00451
00452
00453 if(NC_ndirty(ncp))
00454 {
00455 return write_numrecs(ncp);
00456 }
00457
00458
00459 return NC_NOERR;
00460 }
00461
00462
00463
00464
00465
00466 static int
00467 fillerup(NC *ncp)
00468 {
00469 int status = NC_NOERR;
00470 size_t ii;
00471 NC_var **varpp;
00472
00473 assert(!NC_readonly(ncp));
00474 assert(NC_dofill(ncp));
00475
00476
00477 varpp = ncp->vars.value;
00478 for(ii = 0; ii < ncp->vars.nelems; ii++, varpp++)
00479 {
00480 if(IS_RECVAR(*varpp))
00481 {
00482
00483 continue;
00484 }
00485
00486 status = fill_NC_var(ncp, *varpp, 0);
00487 if(status != NC_NOERR)
00488 break;
00489 }
00490 return status;
00491 }
00492
00493
00494
00495
00496
00497 static int
00498 fill_added_recs(NC *gnu, NC *old)
00499 {
00500 NC_var ** const gnu_varpp = (NC_var **)gnu->vars.value;
00501
00502 const int old_nrecs = (int) NC_get_numrecs(old);
00503 int recno = 0;
00504 for(; recno < old_nrecs; recno++)
00505 {
00506 int varid = (int)old->vars.nelems;
00507 for(; varid < (int)gnu->vars.nelems; varid++)
00508 {
00509 const NC_var *const gnu_varp = *(gnu_varpp + varid);
00510 if(!IS_RECVAR(gnu_varp))
00511 {
00512
00513 continue;
00514 }
00515
00516 {
00517 const int status = fill_NC_var(gnu, gnu_varp, recno);
00518 if(status != NC_NOERR)
00519 return status;
00520 }
00521 }
00522 }
00523
00524 return NC_NOERR;
00525 }
00526
00527
00528
00529 static int
00530 fill_added(NC *gnu, NC *old)
00531 {
00532 NC_var ** const gnu_varpp = (NC_var **)gnu->vars.value;
00533 int varid = (int)old->vars.nelems;
00534
00535 for(; varid < (int)gnu->vars.nelems; varid++)
00536 {
00537 const NC_var *const gnu_varp = *(gnu_varpp + varid);
00538 if(IS_RECVAR(gnu_varp))
00539 {
00540
00541 continue;
00542 }
00543
00544 {
00545 const int status = fill_NC_var(gnu, gnu_varp, 0);
00546 if(status != NC_NOERR)
00547 return status;
00548 }
00549 }
00550
00551 return NC_NOERR;
00552 }
00553
00554
00555
00556
00557
00558
00559 static int
00560 move_recs_r(NC *gnu, NC *old)
00561 {
00562 int status;
00563 int recno;
00564 int varid;
00565 NC_var **gnu_varpp = (NC_var **)gnu->vars.value;
00566 NC_var **old_varpp = (NC_var **)old->vars.value;
00567 NC_var *gnu_varp;
00568 NC_var *old_varp;
00569 off_t gnu_off;
00570 off_t old_off;
00571 const size_t old_nrecs = NC_get_numrecs(old);
00572
00573
00574 for(recno = (int)old_nrecs -1; recno >= 0; recno--)
00575 {
00576
00577 for(varid = (int)old->vars.nelems -1; varid >= 0; varid--)
00578 {
00579 gnu_varp = *(gnu_varpp + varid);
00580 if(!IS_RECVAR(gnu_varp))
00581 {
00582
00583 continue;
00584 }
00585
00586
00587
00588 old_varp = *(old_varpp + varid);
00589 gnu_off = gnu_varp->begin + (off_t)(gnu->recsize * recno);
00590 old_off = old_varp->begin + (off_t)(old->recsize * recno);
00591
00592 if(gnu_off == old_off)
00593 continue;
00594
00595 assert(gnu_off > old_off);
00596
00597 status = gnu->nciop->move(gnu->nciop, gnu_off, old_off,
00598 old_varp->len, 0);
00599
00600 if(status != NC_NOERR)
00601 return status;
00602
00603 }
00604 }
00605
00606 NC_set_numrecs(gnu, old_nrecs);
00607
00608 return NC_NOERR;
00609 }
00610
00611
00612
00613
00614
00615
00616 static int
00617 move_vars_r(NC *gnu, NC *old)
00618 {
00619 int status;
00620 int varid;
00621 NC_var **gnu_varpp = (NC_var **)gnu->vars.value;
00622 NC_var **old_varpp = (NC_var **)old->vars.value;
00623 NC_var *gnu_varp;
00624 NC_var *old_varp;
00625 off_t gnu_off;
00626 off_t old_off;
00627
00628
00629 for(varid = (int)old->vars.nelems -1;
00630 varid >= 0; varid--)
00631 {
00632 gnu_varp = *(gnu_varpp + varid);
00633 if(IS_RECVAR(gnu_varp))
00634 {
00635
00636 continue;
00637 }
00638
00639
00640 old_varp = *(old_varpp + varid);
00641 gnu_off = gnu_varp->begin;
00642 old_off = old_varp->begin;
00643
00644 if(gnu_off == old_off)
00645 continue;
00646
00647 assert(gnu_off > old_off);
00648
00649 status = gnu->nciop->move(gnu->nciop, gnu_off, old_off,
00650 old_varp->len, 0);
00651
00652 if(status != NC_NOERR)
00653 return status;
00654
00655 }
00656
00657 return NC_NOERR;
00658 }
00659
00660
00661
00662
00663
00664
00665 static int
00666 NC_check_vlens(NC *ncp)
00667 {
00668 NC_var **vpp;
00669
00670
00671
00672 size_t vlen_max;
00673 size_t ii;
00674 size_t large_vars_count;
00675 size_t rec_vars_count;
00676 int last;
00677
00678 if(ncp->vars.nelems == 0)
00679 return NC_NOERR;
00680
00681 if ((ncp->flags & NC_64BIT_OFFSET) && sizeof(off_t) > 4) {
00682
00683 vlen_max = X_UINT_MAX - 3;
00684 } else {
00685
00686 vlen_max = X_INT_MAX - 3;
00687 }
00688
00689 large_vars_count = 0;
00690 rec_vars_count = 0;
00691 vpp = ncp->vars.value;
00692 for (ii = 0; ii < ncp->vars.nelems; ii++, vpp++) {
00693 if( !IS_RECVAR(*vpp) ) {
00694 last = 0;
00695 if( NC_check_vlen(*vpp, vlen_max) == 0 ) {
00696 large_vars_count++;
00697 last = 1;
00698 }
00699 } else {
00700 rec_vars_count++;
00701 }
00702 }
00703
00704
00705 if( large_vars_count > 1) {
00706 return NC_EVARSIZE;
00707 }
00708
00709 if( large_vars_count == 1 && last == 0) {
00710 return NC_EVARSIZE;
00711 }
00712 if( rec_vars_count > 0 ) {
00713
00714 if( large_vars_count == 1 && last == 1) {
00715 return NC_EVARSIZE;
00716 }
00717
00718 large_vars_count = 0;
00719 vpp = ncp->vars.value;
00720 for (ii = 0; ii < ncp->vars.nelems; ii++, vpp++) {
00721 if( IS_RECVAR(*vpp) ) {
00722 last = 0;
00723 if( NC_check_vlen(*vpp, vlen_max) == 0 ) {
00724 large_vars_count++;
00725 last = 1;
00726 }
00727 }
00728 }
00729
00730
00731 if( large_vars_count > 1) {
00732 return NC_EVARSIZE;
00733 }
00734
00735 if( large_vars_count == 1 && last == 0) {
00736 return NC_EVARSIZE;
00737 }
00738 }
00739 return NC_NOERR;
00740 }
00741
00742
00743
00744
00745
00746
00747
00748 static int
00749 NC_endef(NC *ncp,
00750 size_t h_minfree, size_t v_align,
00751 size_t v_minfree, size_t r_align)
00752 {
00753 int status = NC_NOERR;
00754
00755 assert(!NC_readonly(ncp));
00756 assert(NC_indef(ncp));
00757
00758 status = NC_check_vlens(ncp);
00759 if(status != NC_NOERR)
00760 return status;
00761 status = NC_begins(ncp, h_minfree, v_align, v_minfree, r_align);
00762 if(status != NC_NOERR)
00763 return status;
00764
00765 if(ncp->old != NULL)
00766 {
00767
00768 assert(!NC_IsNew(ncp));
00769 assert(fIsSet(ncp->flags, NC_INDEF));
00770 assert(ncp->begin_rec >= ncp->old->begin_rec);
00771 assert(ncp->begin_var >= ncp->old->begin_var);
00772
00773 if(ncp->vars.nelems != 0)
00774 {
00775 if(ncp->begin_rec > ncp->old->begin_rec)
00776 {
00777 status = move_recs_r(ncp, ncp->old);
00778 if(status != NC_NOERR)
00779 return status;
00780 if(ncp->begin_var > ncp->old->begin_var)
00781 {
00782 status = move_vars_r(ncp, ncp->old);
00783 if(status != NC_NOERR)
00784 return status;
00785 }
00786
00787 }
00788 else
00789 {
00790
00791
00792 if(ncp->recsize > ncp->old->recsize)
00793 {
00794 status = move_recs_r(ncp, ncp->old);
00795 if(status != NC_NOERR)
00796 return status;
00797 }
00798 }
00799 }
00800 }
00801
00802 status = write_NC(ncp);
00803 if(status != NC_NOERR)
00804 return status;
00805
00806 if(NC_dofill(ncp))
00807 {
00808 if(NC_IsNew(ncp))
00809 {
00810 status = fillerup(ncp);
00811 if(status != NC_NOERR)
00812 return status;
00813
00814 }
00815 else if(ncp->vars.nelems > ncp->old->vars.nelems)
00816 {
00817 status = fill_added(ncp, ncp->old);
00818 if(status != NC_NOERR)
00819 return status;
00820 status = fill_added_recs(ncp, ncp->old);
00821 if(status != NC_NOERR)
00822 return status;
00823 }
00824 }
00825
00826 if(ncp->old != NULL)
00827 {
00828 free_NC(ncp->old);
00829 ncp->old = NULL;
00830 }
00831
00832 fClr(ncp->flags, NC_CREAT | NC_INDEF);
00833
00834 return ncp->nciop->sync(ncp->nciop);
00835 }
00836
00837 #ifdef LOCKNUMREC
00838 static int
00839 NC_init_pe(NC *ncp, int basepe) {
00840 if (basepe < 0 || basepe >= _num_pes()) {
00841 return NC_EINVAL;
00842 }
00843
00844 ncp->lock[LOCKNUMREC_VALUE] = 0;
00845 ncp->lock[LOCKNUMREC_LOCK] = 0;
00846 ncp->lock[LOCKNUMREC_SERVING] = 0;
00847 ncp->lock[LOCKNUMREC_BASEPE] = basepe;
00848 return NC_NOERR;
00849 }
00850 #endif
00851
00852
00853
00854
00855
00856 int
00857 NC_calcsize(NC *ncp, off_t *calcsizep)
00858 {
00859 NC_var **vpp = (NC_var **)ncp->vars.value;
00860 NC_var *const *const end = &vpp[ncp->vars.nelems];
00861 NC_var *last_fix = NULL;
00862 NC_var *last_rec = NULL;
00863
00864 int status;
00865 int numrecvars = 0;
00866
00867 if(ncp->vars.nelems == 0) {
00868
00869 *calcsizep = ncp->xsz;
00870 return NC_NOERR;
00871 }
00872
00873 for( ; vpp < end; vpp++) {
00874 status = NC_var_shape(*vpp, &ncp->dims);
00875 if(status != NC_NOERR)
00876 return status;
00877 if(IS_RECVAR(*vpp)) {
00878 last_rec = *vpp;
00879 numrecvars++;
00880 } else {
00881 last_fix = *vpp;
00882 }
00883 }
00884
00885 if(numrecvars == 0) {
00886 assert(last_fix != NULL);
00887 *calcsizep = last_fix->begin + last_fix->len;
00888
00889 } else {
00890 *calcsizep = ncp->begin_rec + ncp->numrecs * ncp->recsize;
00891
00892 }
00893
00894 return NC_NOERR;
00895 }
00896
00897
00898
00899 int
00900 nc__create(const char * path, int ioflags, size_t initialsz,
00901 size_t *chunksizehintp, int *ncid_ptr)
00902 {
00903 return nc__create_mp(path, ioflags, initialsz, 0,
00904 chunksizehintp, ncid_ptr);
00905 }
00906
00907 int
00908 nc__create_mp(const char * path, int ioflags, size_t initialsz, int basepe,
00909 size_t *chunksizehintp, int *ncid_ptr)
00910 {
00911 NC *ncp;
00912 int status;
00913 void *xp = NULL;
00914 int sizeof_off_t = 0;
00915
00916 #if ALWAYS_NC_SHARE
00917 fSet(ioflags, NC_SHARE);
00918 #endif
00919
00920 ncp = new_NC(chunksizehintp);
00921 if(ncp == NULL)
00922 return NC_ENOMEM;
00923
00924 #if defined(LOCKNUMREC)
00925 if (status = NC_init_pe(ncp, basepe)) {
00926 return status;
00927 }
00928 #else
00929
00930
00931
00932 if(basepe != 0)
00933 return NC_EINVAL;
00934 #endif
00935
00936 assert(ncp->flags == 0);
00937
00938
00939 if (default_create_format == NC_FORMAT_64BIT)
00940 ioflags |= NC_64BIT_OFFSET;
00941
00942 if (fIsSet(ioflags, NC_64BIT_OFFSET)) {
00943 fSet(ncp->flags, NC_64BIT_OFFSET);
00944 sizeof_off_t = 8;
00945 } else {
00946 sizeof_off_t = 4;
00947 }
00948
00949 assert(ncp->xsz == ncx_len_NC(ncp,sizeof_off_t));
00950
00951 status = ncio_create(path, ioflags,
00952 initialsz,
00953 0, ncp->xsz, &ncp->chunk,
00954 &ncp->nciop, &xp);
00955 if(status != NC_NOERR)
00956 {
00957
00958 if(status == EEXIST)
00959 status = NC_EEXIST;
00960 goto unwind_alloc;
00961 }
00962
00963 fSet(ncp->flags, NC_CREAT);
00964
00965 if(fIsSet(ncp->nciop->ioflags, NC_SHARE))
00966 {
00967
00968
00969
00970
00971
00972
00973
00974 fSet(ncp->flags, NC_NSYNC);
00975 }
00976
00977 status = ncx_put_NC(ncp, &xp, sizeof_off_t, ncp->xsz);
00978 if(status != NC_NOERR)
00979 goto unwind_ioc;
00980
00981 add_to_NCList(ncp);
00982
00983 if(chunksizehintp != NULL)
00984 *chunksizehintp = ncp->chunk;
00985 *ncid_ptr = ncp->nciop->fd;
00986 return NC_NOERR;
00987
00988 unwind_ioc:
00989 (void) ncio_close(ncp->nciop, 1);
00990 ncp->nciop = NULL;
00991
00992 unwind_alloc:
00993 free_NC(ncp);
00994 return status;
00995 }
00996
00997
00998
00999
01000
01001
01002 int
01003 nc_set_default_format(int format, int *old_formatp)
01004 {
01005
01006 if (old_formatp)
01007 *old_formatp = default_create_format;
01008
01009
01010 #ifdef USE_NETCDF4
01011 if (format != NC_FORMAT_CLASSIC && format != NC_FORMAT_64BIT &&
01012 format != NC_FORMAT_NETCDF4 && format != NC_FORMAT_NETCDF4_CLASSIC)
01013 return NC_EINVAL;
01014 #else
01015 if (format != NC_FORMAT_CLASSIC && format != NC_FORMAT_64BIT)
01016 return NC_EINVAL;
01017 #endif
01018 default_create_format = format;
01019 return NC_NOERR;
01020 }
01021
01022 int
01023 nc_create(const char * path, int ioflags, int *ncid_ptr)
01024 {
01025 return nc__create(path, ioflags, 0, NULL, ncid_ptr);
01026 }
01027
01028 int
01029 nc__open(const char * path, int ioflags,
01030 size_t *chunksizehintp, int *ncid_ptr)
01031 {
01032 return nc__open_mp(path, ioflags, 0,
01033 chunksizehintp, ncid_ptr);
01034 }
01035
01036 int
01037 nc__open_mp(const char * path, int ioflags, int basepe,
01038 size_t *chunksizehintp, int *ncid_ptr)
01039 {
01040 NC *ncp;
01041 int status;
01042
01043 #if ALWAYS_NC_SHARE
01044 fSet(ioflags, NC_SHARE);
01045 #endif
01046
01047 ncp = new_NC(chunksizehintp);
01048 if(ncp == NULL)
01049 return NC_ENOMEM;
01050
01051 #if defined(LOCKNUMREC)
01052 if (status = NC_init_pe(ncp, basepe)) {
01053 return status;
01054 }
01055 #else
01056
01057
01058
01059 if(basepe != 0)
01060 return NC_EINVAL;
01061 #endif
01062
01063 status = ncio_open(path, ioflags,
01064 0, 0, &ncp->chunk,
01065 &ncp->nciop, 0);
01066 if(status)
01067 goto unwind_alloc;
01068
01069 assert(ncp->flags == 0);
01070
01071 if(fIsSet(ncp->nciop->ioflags, NC_SHARE))
01072 {
01073
01074
01075
01076
01077
01078
01079
01080 fSet(ncp->flags, NC_NSYNC);
01081 }
01082
01083 status = nc_get_NC(ncp);
01084 if(status != NC_NOERR)
01085 goto unwind_ioc;
01086
01087 add_to_NCList(ncp);
01088
01089 if(chunksizehintp != NULL)
01090 *chunksizehintp = ncp->chunk;
01091 *ncid_ptr = ncp->nciop->fd;
01092 return NC_NOERR;
01093
01094 unwind_ioc:
01095 (void) ncio_close(ncp->nciop, 0);
01096 ncp->nciop = NULL;
01097
01098 unwind_alloc:
01099 free_NC(ncp);
01100 return status;
01101 }
01102
01103 int
01104 nc_open(const char * path, int ioflags, int *ncid_ptr)
01105 {
01106 return nc__open(path, ioflags, NULL, ncid_ptr);
01107 }
01108
01109
01110 int
01111 nc__enddef(int ncid,
01112 size_t h_minfree, size_t v_align,
01113 size_t v_minfree, size_t r_align)
01114 {
01115 int status;
01116 NC *ncp;
01117
01118 status = NC_check_id(ncid, &ncp);
01119 if(status != NC_NOERR)
01120 return status;
01121
01122 if(!NC_indef(ncp))
01123 return(NC_ENOTINDEFINE);
01124
01125 return (NC_endef(ncp, h_minfree, v_align, v_minfree, r_align));
01126 }
01127
01128 int
01129 nc_enddef(int ncid)
01130 {
01131 int status;
01132 NC *ncp;
01133
01134 status = NC_check_id(ncid, &ncp);
01135 if(status != NC_NOERR)
01136 return status;
01137
01138 if(!NC_indef(ncp))
01139 return(NC_ENOTINDEFINE);
01140
01141
01142 return (NC_endef(ncp, 0, 1, 0, 1));
01143 }
01144
01145
01146 int
01147 nc_close(int ncid)
01148 {
01149 int status = NC_NOERR;
01150 NC *ncp;
01151
01152 status = NC_check_id(ncid, &ncp);
01153 if(status != NC_NOERR)
01154 return status;
01155
01156 if(NC_indef(ncp))
01157 {
01158 status = NC_endef(ncp, 0, 1, 0, 1);
01159 if(status != NC_NOERR )
01160 {
01161 (void) nc_abort(ncid);
01162 return status;
01163 }
01164 }
01165 else if(!NC_readonly(ncp))
01166 {
01167 status = NC_sync(ncp);
01168 }
01169
01170
01171
01172
01173
01174
01175 {
01176 off_t filesize;
01177 off_t calcsize;
01178 status = ncio_filesize(ncp->nciop, &filesize);
01179 if(status != ENOERR)
01180 return status;
01181 status = NC_calcsize(ncp, &calcsize);
01182 if(status != NC_NOERR)
01183 return status;
01184 if(filesize < calcsize && !NC_readonly(ncp)) {
01185 status = ncio_pad_length(ncp->nciop, calcsize);
01186 if(status != ENOERR)
01187 return status;
01188 }
01189
01190 }
01191
01192 (void) ncio_close(ncp->nciop, 0);
01193 ncp->nciop = NULL;
01194
01195 del_from_NCList(ncp);
01196
01197 free_NC(ncp);
01198
01199 return status;
01200 }
01201
01202
01203 int
01204 nc_delete(const char * path)
01205 {
01206 return nc_delete_mp(path, 0);
01207 }
01208
01209 int
01210 nc_delete_mp(const char * path, int basepe)
01211 {
01212 NC *ncp;
01213 int status;
01214 size_t chunk = 512;
01215
01216 ncp = new_NC(&chunk);
01217 if(ncp == NULL)
01218 return NC_ENOMEM;
01219
01220 #if defined(LOCKNUMREC)
01221 if (status = NC_init_pe(ncp, basepe)) {
01222 return status;
01223 }
01224 #else
01225
01226
01227
01228 if(basepe != 0)
01229 return NC_EINVAL;
01230 #endif
01231 status = ncio_open(path, NC_NOWRITE,
01232 0, 0, &ncp->chunk,
01233 &ncp->nciop, 0);
01234 if(status)
01235 goto unwind_alloc;
01236
01237 assert(ncp->flags == 0);
01238
01239 status = nc_get_NC(ncp);
01240 if(status != NC_NOERR)
01241 {
01242
01243
01244 (void) ncio_close(ncp->nciop, 0);
01245 }
01246 else
01247 {
01248
01249 status = ncio_close(ncp->nciop, 1);
01250 }
01251
01252 ncp->nciop = NULL;
01253 unwind_alloc:
01254 free_NC(ncp);
01255 return status;
01256 }
01257
01258
01259
01260
01261
01262
01263
01264 int
01265 nc_abort(int ncid)
01266 {
01267 int status;
01268 NC *ncp;
01269 int doUnlink = 0;
01270
01271 status = NC_check_id(ncid, &ncp);
01272 if(status != NC_NOERR)
01273 return status;
01274
01275 doUnlink = NC_IsNew(ncp);
01276
01277 if(ncp->old != NULL)
01278 {
01279
01280 assert(!NC_IsNew(ncp));
01281 assert(fIsSet(ncp->flags, NC_INDEF));
01282 free_NC(ncp->old);
01283 ncp->old = NULL;
01284 fClr(ncp->flags, NC_INDEF);
01285 }
01286 else if(!NC_readonly(ncp))
01287 {
01288 status = NC_sync(ncp);
01289 if(status != NC_NOERR)
01290 return status;
01291 }
01292
01293
01294 (void) ncio_close(ncp->nciop, doUnlink);
01295 ncp->nciop = NULL;
01296
01297 del_from_NCList(ncp);
01298
01299 free_NC(ncp);
01300
01301 return NC_NOERR;
01302 }
01303
01304
01305 int
01306 nc_redef(int ncid)
01307 {
01308 int status;
01309 NC *ncp;
01310
01311 status = NC_check_id(ncid, &ncp);
01312 if(status != NC_NOERR)
01313 return status;
01314
01315 if(NC_readonly(ncp))
01316 return NC_EPERM;
01317
01318 if(NC_indef(ncp))
01319 return NC_EINDEFINE;
01320
01321
01322 if(fIsSet(ncp->nciop->ioflags, NC_SHARE))
01323 {
01324
01325 status = read_NC(ncp);
01326 if(status != NC_NOERR)
01327 return status;
01328 }
01329
01330 ncp->old = dup_NC(ncp);
01331 if(ncp->old == NULL)
01332 return NC_ENOMEM;
01333
01334 fSet(ncp->flags, NC_INDEF);
01335
01336 return NC_NOERR;
01337 }
01338
01339
01340 int
01341 nc_inq(int ncid,
01342 int *ndimsp,
01343 int *nvarsp,
01344 int *nattsp,
01345 int *xtendimp)
01346 {
01347 int status;
01348 NC *ncp;
01349
01350 status = NC_check_id(ncid, &ncp);
01351 if(status != NC_NOERR)
01352 return status;
01353
01354 if(ndimsp != NULL)
01355 *ndimsp = (int) ncp->dims.nelems;
01356 if(nvarsp != NULL)
01357 *nvarsp = (int) ncp->vars.nelems;
01358 if(nattsp != NULL)
01359 *nattsp = (int) ncp->attrs.nelems;
01360 if(xtendimp != NULL)
01361 *xtendimp = find_NC_Udim(&ncp->dims, NULL);
01362
01363 return NC_NOERR;
01364 }
01365
01366 int
01367 nc_inq_ndims(int ncid, int *ndimsp)
01368 {
01369 int status;
01370 NC *ncp;
01371
01372 status = NC_check_id(ncid, &ncp);
01373 if(status != NC_NOERR)
01374 return status;
01375
01376 if(ndimsp != NULL)
01377 *ndimsp = (int) ncp->dims.nelems;
01378
01379 return NC_NOERR;
01380 }
01381
01382 int
01383 nc_inq_nvars(int ncid, int *nvarsp)
01384 {
01385 int status;
01386 NC *ncp;
01387
01388 status = NC_check_id(ncid, &ncp);
01389 if(status != NC_NOERR)
01390 return status;
01391
01392 if(nvarsp != NULL)
01393 *nvarsp = (int) ncp->vars.nelems;
01394
01395 return NC_NOERR;
01396 }
01397
01398 int
01399 nc_inq_natts(int ncid, int *nattsp)
01400 {
01401 int status;
01402 NC *ncp;
01403
01404 status = NC_check_id(ncid, &ncp);
01405 if(status != NC_NOERR)
01406 return status;
01407
01408 if(nattsp != NULL)
01409 *nattsp = (int) ncp->attrs.nelems;
01410
01411 return NC_NOERR;
01412 }
01413
01414 int
01415 nc_inq_unlimdim(int ncid, int *xtendimp)
01416 {
01417 int status;
01418 NC *ncp;
01419
01420 status = NC_check_id(ncid, &ncp);
01421 if(status != NC_NOERR)
01422 return status;
01423
01424 if(xtendimp != NULL)
01425 *xtendimp = find_NC_Udim(&ncp->dims, NULL);
01426
01427 return NC_NOERR;
01428 }
01429
01430
01431 int
01432 nc_sync(int ncid)
01433 {
01434 int status;
01435 NC *ncp;
01436
01437 status = NC_check_id(ncid, &ncp);
01438 if(status != NC_NOERR)
01439 return status;
01440
01441 if(NC_indef(ncp))
01442 return NC_EINDEFINE;
01443
01444 if(NC_readonly(ncp))
01445 {
01446 return read_NC(ncp);
01447 }
01448
01449
01450 status = NC_sync(ncp);
01451 if(status != NC_NOERR)
01452 return status;
01453
01454 return ncp->nciop->sync(ncp->nciop);
01455 }
01456
01457
01458 int
01459 nc_set_fill(int ncid,
01460 int fillmode, int *old_mode_ptr)
01461 {
01462 int status;
01463 NC *ncp;
01464 int oldmode;
01465
01466 status = NC_check_id(ncid, &ncp);
01467 if(status != NC_NOERR)
01468 return status;
01469
01470 if(NC_readonly(ncp))
01471 return NC_EPERM;
01472
01473 oldmode = fIsSet(ncp->flags, NC_NOFILL) ? NC_NOFILL : NC_FILL;
01474
01475 if(fillmode == NC_NOFILL)
01476 {
01477 fSet(ncp->flags, NC_NOFILL);
01478 }
01479 else if(fillmode == NC_FILL)
01480 {
01481 if(fIsSet(ncp->flags, NC_NOFILL))
01482 {
01483
01484
01485
01486
01487 status = NC_sync(ncp);
01488 if(status != NC_NOERR)
01489 return status;
01490 }
01491 fClr(ncp->flags, NC_NOFILL);
01492 }
01493 else
01494 {
01495 return NC_EINVAL;
01496 }
01497
01498 if(old_mode_ptr != NULL)
01499 *old_mode_ptr = oldmode;
01500
01501 return NC_NOERR;
01502 }
01503
01504 #ifdef LOCKNUMREC
01505
01506
01507 size_t NC_get_numrecs(const NC *ncp) {
01508 shmem_t numrec;
01509 shmem_short_get(&numrec, (shmem_t *) ncp->lock + LOCKNUMREC_VALUE, 1,
01510 ncp->lock[LOCKNUMREC_BASEPE]);
01511 return (size_t) numrec;
01512 }
01513
01514 void NC_set_numrecs(NC *ncp, size_t nrecs) {
01515 shmem_t numrec = (shmem_t) nrecs;
01516
01517 ncp->lock[LOCKNUMREC_VALUE] = (ushmem_t) numrec;
01518 shmem_short_put((shmem_t *) ncp->lock + LOCKNUMREC_VALUE, &numrec, 1,
01519 ncp->lock[LOCKNUMREC_BASEPE]);
01520 }
01521
01522 void NC_increase_numrecs(NC *ncp, size_t nrecs) {
01523
01524
01525 if (nrecs > NC_get_numrecs(ncp))
01526 NC_set_numrecs(ncp, nrecs);
01527 }
01528
01529 #endif
01530
01531
01532
01533 int
01534 nc_set_base_pe(int ncid, int pe)
01535 {
01536 #if _CRAYMPP && defined(LOCKNUMREC)
01537 int status;
01538 NC *ncp;
01539 shmem_t numrecs;
01540
01541 if ((status = NC_check_id(ncid, &ncp)) != NC_NOERR) {
01542 return status;
01543 }
01544 if (pe < 0 || pe >= _num_pes()) {
01545 return NC_EINVAL;
01546 }
01547
01548 numrecs = (shmem_t) NC_get_numrecs(ncp);
01549
01550 ncp->lock[LOCKNUMREC_VALUE] = (ushmem_t) numrecs;
01551
01552
01553
01554
01555
01556 shmem_short_get(
01557 (shmem_t *) ncp->lock + LOCKNUMREC_SERVING,
01558 (shmem_t *) ncp->lock + LOCKNUMREC_SERVING,
01559 1, ncp->lock[LOCKNUMREC_BASEPE]);
01560
01561 shmem_short_get(
01562 (shmem_t *) ncp->lock + LOCKNUMREC_LOCK,
01563 (shmem_t *) ncp->lock + LOCKNUMREC_LOCK,
01564 1, ncp->lock[LOCKNUMREC_BASEPE]);
01565
01566
01567 ncp->lock[LOCKNUMREC_BASEPE] = (ushmem_t) pe;
01568
01569 #endif
01570 return NC_NOERR;
01571 }
01572
01573
01574 int
01575 nc_inq_base_pe(int ncid, int *pe)
01576 {
01577 #if _CRAYMPP && defined(LOCKNUMREC)
01578 int status;
01579 NC *ncp;
01580
01581 if ((status = NC_check_id(ncid, &ncp)) != NC_NOERR) {
01582 return status;
01583 }
01584
01585 *pe = (int) ncp->lock[LOCKNUMREC_BASEPE];
01586 #else
01587
01588
01589
01590 *pe = 0;
01591 #endif
01592 return NC_NOERR;
01593 }
01594
01595 int
01596 nc_inq_format(int ncid, int *formatp)
01597 {
01598 int status;
01599 NC *ncp;
01600
01601 status = NC_check_id(ncid, &ncp);
01602 if(status != NC_NOERR)
01603 return status;
01604
01605
01606
01607 *formatp = fIsSet(ncp->flags, NC_64BIT_OFFSET) ? NC_FORMAT_64BIT
01608 : NC_FORMAT_CLASSIC;
01609 return NC_NOERR;
01610 }