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