📄 nc.c
字号:
static intfill_added(NC *gnu, NC *old){ NC_var ** const gnu_varpp = (NC_var **)gnu->vars.value; int varid = (int)old->vars.nelems; for(; varid < (int)gnu->vars.nelems; varid++) { const NC_var *const gnu_varp = *(gnu_varpp + varid); if(IS_RECVAR(gnu_varp)) { /* skip record variables */ continue; } /* else */ { const int status = fill_NC_var(gnu, gnu_varp, gnu_varp->len, 0); if(status != NC_NOERR) return status; } } return NC_NOERR;}/* * Move the records "out". * Fill as needed. */static intmove_recs_r(NC *gnu, NC *old){ int status; int recno; int varid; NC_var **gnu_varpp = (NC_var **)gnu->vars.value; NC_var **old_varpp = (NC_var **)old->vars.value; NC_var *gnu_varp; NC_var *old_varp; off_t gnu_off; off_t old_off; const size_t old_nrecs = NC_get_numrecs(old); /* Don't parallelize this loop */ for(recno = (int)old_nrecs -1; recno >= 0; recno--) { /* Don't parallelize this loop */ for(varid = (int)old->vars.nelems -1; varid >= 0; varid--) { gnu_varp = *(gnu_varpp + varid); if(!IS_RECVAR(gnu_varp)) { /* skip non-record variables on this pass */ continue; } /* else */ /* else, a pre-existing variable */ old_varp = *(old_varpp + varid); gnu_off = gnu_varp->begin + (off_t)(gnu->recsize * recno); old_off = old_varp->begin + (off_t)(old->recsize * recno); if(gnu_off == old_off) continue; /* nothing to do */ assert(gnu_off > old_off); status = gnu->nciop->move(gnu->nciop, gnu_off, old_off, old_varp->len, 0); if(status != NC_NOERR) return status; } } NC_set_numrecs(gnu, old_nrecs); return NC_NOERR;}/* * Move the "non record" variables "out". * Fill as needed. */static intmove_vars_r(NC *gnu, NC *old){ int status; int varid; NC_var **gnu_varpp = (NC_var **)gnu->vars.value; NC_var **old_varpp = (NC_var **)old->vars.value; NC_var *gnu_varp; NC_var *old_varp; off_t gnu_off; off_t old_off; /* Don't parallelize this loop */ for(varid = (int)old->vars.nelems -1; varid >= 0; varid--) { gnu_varp = *(gnu_varpp + varid); if(IS_RECVAR(gnu_varp)) { /* skip record variables on this pass */ continue; } /* else */ old_varp = *(old_varpp + varid); gnu_off = gnu_varp->begin; old_off = old_varp->begin; if(gnu_off == old_off) continue; /* nothing to do */ assert(gnu_off > old_off); status = gnu->nciop->move(gnu->nciop, gnu_off, old_off, old_varp->len, 0); if(status != NC_NOERR) return status; } return NC_NOERR;}/* * Given a valid ncp, return NC_EVARSIZE if any variable has a bad len * (product of non-rec dim sizes too large), else return NC_NOERR. */static intNC_check_vlens(NC *ncp){ NC_var **vpp; /* maximum permitted variable size (or size of one record's worth of a record variable) in bytes. This is different for format 1 and format 2. */ size_t vlen_max; size_t ii; size_t large_vars_count; size_t rec_vars_count; int last = 0; if(ncp->vars.nelems == 0) return NC_NOERR; if ((ncp->flags & NC_64BIT_OFFSET) && sizeof(off_t) > 4) { /* CDF2 format and LFS */ vlen_max = X_UINT_MAX - 3; /* "- 3" handles rounded-up size */ } else { /* CDF1 format */ vlen_max = X_INT_MAX - 3; } /* Loop through vars, first pass is for non-record variables. */ large_vars_count = 0; rec_vars_count = 0; vpp = ncp->vars.value; for (ii = 0; ii < ncp->vars.nelems; ii++, vpp++) { if( !IS_RECVAR(*vpp) ) { last = 0; if( NC_check_vlen(*vpp, vlen_max) == 0 ) { large_vars_count++; last = 1; } } else { rec_vars_count++; } } /* OK if last non-record variable size too large, since not used to compute an offset */ if( large_vars_count > 1) { /* only one "too-large" variable allowed */ return NC_EVARSIZE; } /* and it has to be the last one */ if( large_vars_count == 1 && last == 0) { return NC_EVARSIZE; } if( rec_vars_count > 0 ) { /* and if it's the last one, there can't be any record variables */ if( large_vars_count == 1 && last == 1) { return NC_EVARSIZE; } /* Loop through vars, second pass is for record variables. */ large_vars_count = 0; vpp = ncp->vars.value; for (ii = 0; ii < ncp->vars.nelems; ii++, vpp++) { if( IS_RECVAR(*vpp) ) { last = 0; if( NC_check_vlen(*vpp, vlen_max) == 0 ) { large_vars_count++; last = 1; } } } /* OK if last record variable size too large, since not used to compute an offset */ if( large_vars_count > 1) { /* only one "too-large" variable allowed */ return NC_EVARSIZE; } /* and it has to be the last one */ if( large_vars_count == 1 && last == 0) { return NC_EVARSIZE; } } return NC_NOERR;}/* * End define mode. * Common code for ncendef, ncclose(endef) * Flushes I/O buffers. */static intNC_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);}#ifdef LOCKNUMRECstatic intNC_init_pe(NC *ncp, int basepe) { if (basepe < 0 || basepe >= _num_pes()) { return NC_EINVAL; /* invalid base pe */ } /* initialize common values */ ncp->lock[LOCKNUMREC_VALUE] = 0; ncp->lock[LOCKNUMREC_LOCK] = 0; ncp->lock[LOCKNUMREC_SERVING] = 0; ncp->lock[LOCKNUMREC_BASEPE] = basepe; return NC_NOERR;}#endif/* * Compute the expected size of the file. */intNC_calcsize(NC *ncp, off_t *calcsizep){ NC_var **vpp = (NC_var **)ncp->vars.value; NC_var *const *const end = &vpp[ncp->vars.nelems]; NC_var *last_fix = NULL; /* last "non-record" var */ NC_var *last_rec = NULL; /* last "record" var */ /*NC_var *last_var;*/ int status; int numrecvars = 0; /* number of record variables */ if(ncp->vars.nelems == 0) { /* no non-record variables and no record variables */ *calcsizep = ncp->xsz; /* size of header */ return NC_NOERR; } for( /*NADA*/; vpp < end; vpp++) { status = NC_var_shape(*vpp, &ncp->dims); if(status != NC_NOERR) return status; if(IS_RECVAR(*vpp)) { last_rec = *vpp; numrecvars++; } else { last_fix = *vpp; } } if(numrecvars == 0) { assert(last_fix != NULL); *calcsizep = last_fix->begin + last_fix->len; /*last_var = last_fix;*/ } else { /* we have at least one record variable */ *calcsizep = ncp->begin_rec + ncp->numrecs * ncp->recsize; /*last_var = last_rec;*/ } return NC_NOERR;}/* Public */intnc__create(const char * path, int ioflags, size_t initialsz, size_t *chunksizehintp, int *ncid_ptr){ return nc__create_mp(path, ioflags, initialsz, 0, chunksizehintp, ncid_ptr);}intnc__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;}/* This function sets a default create flag that will be logically or'd to whatever flags are passed into nc_create for all future calls to nc_create. Valid default create flags are NC_64BIT_OFFSET, NC_CLOBBER, NC_LOCK, NC_SHARE. */intnc_set_default_format(int format, int *old_formatp){ /* Return existing format if desired. */ if (old_formatp) *old_formatp = default_create_format; /* Make sure only valid format is set. */#ifdef USE_NETCDF4 if (format != NC_FORMAT_CLASSIC && format != NC_FORMAT_64BIT && format != NC_FORMAT_NETCDF4 && format != NC_FORMAT_NETCDF4_CLASSIC) return NC_EINVAL;#else if (format != NC_FORMAT_CLASSIC && format != NC_FORMAT_64BIT) return NC_EINVAL;#endif default_create_format = format; return NC_NOERR;}intnc_create(const char * path, int ioflags, int *ncid_ptr){ return nc__create(path, ioflags, 0, NULL, ncid_ptr);}intnc__open(const char * path, int ioflags, size_t *chunksizehintp, int *ncid_ptr){ return nc__open_mp(path, ioflags, 0, chunksizehintp, ncid_ptr);}intnc__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))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -