static NC * dup_NC(const NC *ref) { NC *ncp; #if _CRAYMPP && defined(LOCKNUMREC) ncp = (NC *) shmalloc(sizeof(NC)); #else ncp = (NC *) malloc(sizeof(NC)); #endif /* _CRAYMPP && LOCKNUMREC */ if(ncp == NULL) return NULL; (void) memset(ncp, 0, sizeof(NC)); if(dup_NC_dimarrayV(&ncp->dims, &ref->dims) != NC_NOERR) goto err; if(dup_NC_attrarrayV(&ncp->attrs, &ref->attrs) != NC_NOERR) goto err; if(dup_NC_vararrayV(&ncp->vars, &ref->vars) != NC_NOERR) goto err; ncp->xsz = ref->xsz; ncp->begin_var = ref->begin_var; ncp->begin_rec = ref->begin_rec; ncp->recsize = ref->recsize; NC_set_numrecs(ncp, NC_get_numrecs(ref)); return ncp; err: free_NC(ncp); return NULL; }
int nc_close(int ncid) { int status = NC_NOERR; NC *ncp; status = NC_check_id(ncid, &ncp); if(status != NC_NOERR) return status; if(NC_indef(ncp)) { status = NC_endef(ncp, 0, 1, 0, 1); /* TODO: defaults */ if(status != NC_NOERR ) { (void) nc_abort(ncid); return status; } } else if(!NC_readonly(ncp)) { status = NC_sync(ncp); /* flush buffers before any filesize comparisons */ (void) ncp->nciop->sync(ncp->nciop); } /* * If file opened for writing and filesize is less than * what it should be (due to previous use of NOFILL mode), * pad it to correct size, as reported by NC_calcsize(). */ if (status == ENOERR) { off_t filesize; /* current size of open file */ off_t calcsize; /* calculated file size, from header */ status = ncio_filesize(ncp->nciop, &filesize); if(status != ENOERR) return status; status = NC_calcsize(ncp, &calcsize); if(status != NC_NOERR) return status; if(filesize < calcsize && !NC_readonly(ncp)) { status = ncio_pad_length(ncp->nciop, calcsize); if(status != ENOERR) return status; } } (void) ncio_close(ncp->nciop, 0); ncp->nciop = NULL; del_from_NCList(ncp); free_NC(ncp); return status; }
int new_NC(NC_Dispatch* dispatcher, const char* path, int mode, NC** ncpp) { NC *ncp = (NC*)calloc(1,sizeof(NC)); if(ncp == NULL) return NC_ENOMEM; ncp->dispatch = dispatcher; ncp->path = nulldup(path); ncp->mode = mode; if(ncp->path == NULL) { /* fail */ free_NC(ncp); return NC_ENOMEM; } if(ncpp) { *ncpp = ncp; } else { free_NC(ncp); } return NC_NOERR; }
/* * In data mode, same as ncclose. * In define mode, restore previous definition. * In create, remove the file. */ int nc_abort(int ncid) { int status; NC *ncp; int doUnlink = 0; status = NC_check_id(ncid, &ncp); if(status != NC_NOERR) return status; doUnlink = NC_IsNew(ncp); if(ncp->old != NULL) { /* a plain redef, not a create */ assert(!NC_IsNew(ncp)); assert(fIsSet(ncp->flags, NC_INDEF)); free_NC(ncp->old); ncp->old = NULL; fClr(ncp->flags, NC_INDEF); } else if(!NC_readonly(ncp)) { status = NC_sync(ncp); if(status != NC_NOERR) return status; } (void) ncio_close(ncp->nciop, doUnlink); ncp->nciop = NULL; del_from_NCList(ncp); free_NC(ncp); return NC_NOERR; }
int nc_delete_mp(const char * path, int basepe) { NC *ncp; int status; size_t chunk = 512; ncp = new_NC(&chunk); if(ncp == NULL) return NC_ENOMEM; #if defined(LOCKNUMREC) /* && _CRAYMPP */ if (status = NC_init_pe(ncp, basepe)) { return status; } #else /* * !_CRAYMPP, only pe 0 is valid */ if(basepe != 0) return NC_EINVAL; #endif status = ncio_open(path, NC_NOWRITE, 0, 0, &ncp->chunk, &ncp->nciop, 0); if(status) goto unwind_alloc; assert(ncp->flags == 0); status = nc_get_NC(ncp); if(status != NC_NOERR) { /* Not a netcdf file, don't delete */ /* ??? is this the right semantic? what if it was just too big? */ (void) ncio_close(ncp->nciop, 0); } else { /* ncio_close does the unlink */ status = ncio_close(ncp->nciop, 1); /* ncio_close does the unlink */ } ncp->nciop = NULL; unwind_alloc: free_NC(ncp); return status; }
int nc__create_mp(const char * path, int ioflags, size_t initialsz, int basepe, size_t *chunksizehintp, int *ncid_ptr) { NC *ncp; int status; void *xp = NULL; int sizeof_off_t = 0; #if ALWAYS_NC_SHARE /* DEBUG */ fSet(ioflags, NC_SHARE); #endif ncp = new_NC(chunksizehintp); if(ncp == NULL) return NC_ENOMEM; #if defined(LOCKNUMREC) /* && _CRAYMPP */ if (status = NC_init_pe(ncp, basepe)) { return status; } #else /* * !_CRAYMPP, only pe 0 is valid */ if(basepe != 0) return NC_EINVAL; #endif assert(ncp->flags == 0); /* Apply default create format. */ if (default_create_format == NC_FORMAT_64BIT) ioflags |= NC_64BIT_OFFSET; if (fIsSet(ioflags, NC_64BIT_OFFSET)) { fSet(ncp->flags, NC_64BIT_OFFSET); sizeof_off_t = 8; } else { sizeof_off_t = 4; } assert(ncp->xsz == ncx_len_NC(ncp,sizeof_off_t)); status = ncio_create(path, ioflags, initialsz, 0, ncp->xsz, &ncp->chunk, &ncp->nciop, &xp); if(status != NC_NOERR) { /* translate error status */ if(status == EEXIST) status = NC_EEXIST; goto unwind_alloc; } fSet(ncp->flags, NC_CREAT); if(fIsSet(ncp->nciop->ioflags, NC_SHARE)) { /* * NC_SHARE implies sync up the number of records as well. * (File format version one.) * Note that other header changes are not shared * automatically. Some sort of IPC (external to this package) * would be used to trigger a call to nc_sync(). */ fSet(ncp->flags, NC_NSYNC); } status = ncx_put_NC(ncp, &xp, sizeof_off_t, ncp->xsz); if(status != NC_NOERR) goto unwind_ioc; add_to_NCList(ncp); if(chunksizehintp != NULL) *chunksizehintp = ncp->chunk; *ncid_ptr = ncp->nciop->fd; return NC_NOERR; unwind_ioc: (void) ncio_close(ncp->nciop, 1); /* N.B.: unlink */ ncp->nciop = NULL; /*FALLTHRU*/ unwind_alloc: free_NC(ncp); return status; }
/* * End define mode. * Common code for ncendef, ncclose(endef) * Flushes I/O buffers. */ static int NC_endef(NC *ncp, size_t h_minfree, size_t v_align, size_t v_minfree, size_t r_align) { int status = NC_NOERR; assert(!NC_readonly(ncp)); assert(NC_indef(ncp)); status = NC_check_vlens(ncp); if(status != NC_NOERR) return status; status = NC_begins(ncp, h_minfree, v_align, v_minfree, r_align); if(status != NC_NOERR) return status; if(ncp->old != NULL) { /* a plain redef, not a create */ assert(!NC_IsNew(ncp)); assert(fIsSet(ncp->flags, NC_INDEF)); assert(ncp->begin_rec >= ncp->old->begin_rec); assert(ncp->begin_var >= ncp->old->begin_var); if(ncp->vars.nelems != 0) { if(ncp->begin_rec > ncp->old->begin_rec) { status = move_recs_r(ncp, ncp->old); if(status != NC_NOERR) return status; if(ncp->begin_var > ncp->old->begin_var) { status = move_vars_r(ncp, ncp->old); if(status != NC_NOERR) return status; } /* else if (ncp->begin_var == ncp->old->begin_var) { NOOP } */ } else { /* Even if (ncp->begin_rec == ncp->old->begin_rec) and (ncp->begin_var == ncp->old->begin_var) might still have added a new record variable */ if(ncp->recsize > ncp->old->recsize) { status = move_recs_r(ncp, ncp->old); if(status != NC_NOERR) return status; } } } } status = write_NC(ncp); if(status != NC_NOERR) return status; if(NC_dofill(ncp)) { if(NC_IsNew(ncp)) { status = fillerup(ncp); if(status != NC_NOERR) return status; } else if(ncp->vars.nelems > ncp->old->vars.nelems) { status = fill_added(ncp, ncp->old); if(status != NC_NOERR) return status; status = fill_added_recs(ncp, ncp->old); if(status != NC_NOERR) return status; } } if(ncp->old != NULL) { free_NC(ncp->old); ncp->old = NULL; } fClr(ncp->flags, NC_CREAT | NC_INDEF); return ncp->nciop->sync(ncp->nciop); }
int nc__open_mp(const char * path, int ioflags, int basepe, size_t *chunksizehintp, int *ncid_ptr) { NC *ncp; int status; #if ALWAYS_NC_SHARE /* DEBUG */ fSet(ioflags, NC_SHARE); #endif ncp = new_NC(chunksizehintp); if(ncp == NULL) return NC_ENOMEM; #if defined(LOCKNUMREC) /* && _CRAYMPP */ if (status = NC_init_pe(ncp, basepe)) { return status; } #else /* * !_CRAYMPP, only pe 0 is valid */ if(basepe != 0) return NC_EINVAL; #endif status = ncio_open(path, ioflags, 0, 0, &ncp->chunk, &ncp->nciop, 0); if(status) goto unwind_alloc; assert(ncp->flags == 0); if(fIsSet(ncp->nciop->ioflags, NC_SHARE)) { /* * NC_SHARE implies sync up the number of records as well. * (File format version one.) * Note that other header changes are not shared * automatically. Some sort of IPC (external to this package) * would be used to trigger a call to nc_sync(). */ fSet(ncp->flags, NC_NSYNC); } status = nc_get_NC(ncp); if(status != NC_NOERR) goto unwind_ioc; add_to_NCList(ncp); if(chunksizehintp != NULL) *chunksizehintp = ncp->chunk; *ncid_ptr = ncp->nciop->fd; return NC_NOERR; unwind_ioc: (void) ncio_close(ncp->nciop, 0); ncp->nciop = NULL; /*FALLTHRU*/ unwind_alloc: free_NC(ncp); return status; }