/* Copyright (c) 1998-2018 University Corporation for Atmospheric Research/Unidata See LICENSE.txt for license information. */ #include "config.h" #include "ncdispatch.h" #include "ncuri.h" #include "nclog.h" #include "ncbytes.h" #include "ncrc.h" #include "ncoffsets.h" #include "ncpathmgr.h" #include "ncxml.h" #include "nc4internal.h" /* Required for getcwd, other functions. */ #ifdef HAVE_UNISTD_H #include #endif /* Required for getcwd, other functions. */ #ifdef _WIN32 #include #endif #if defined(NETCDF_ENABLE_BYTERANGE) || defined(NETCDF_ENABLE_DAP) || defined(NETCDF_ENABLE_DAP4) #include #endif #ifdef NETCDF_ENABLE_S3 #include "ncs3sdk.h" #endif #define MAXPATH 1024 /* Define vectors of zeros and ones for use with various nc_get_varX functions */ /* Note, this form of initialization fails under Cygwin */ size_t NC_coord_zero[NC_MAX_VAR_DIMS] = {0}; size_t NC_coord_one[NC_MAX_VAR_DIMS] = {1}; ptrdiff_t NC_stride_one[NC_MAX_VAR_DIMS] = {1}; /* static nc_type longtype = (sizeof(long) == sizeof(int)?NC_INT:NC_INT64); static nc_type ulongtype = (sizeof(unsigned long) == sizeof(unsigned int)?NC_UINT:NC_UINT64); */ /* Allow dispatch to do general initialization and finalization */ int NCDISPATCH_initialize(void) { int status = NC_NOERR; int i; NCglobalstate* globalstate = NULL; for(i=0;itempdir= strdup(tempdir); } /* Capture $HOME */ { #if defined(_WIN32) && !defined(__MINGW32__) char* home = getenv("USERPROFILE"); #else char* home = getenv("HOME"); #endif if(home == NULL) { /* use cwd */ home = malloc(MAXPATH+1); NCgetcwd(home,MAXPATH); } else home = strdup(home); /* make it always free'able */ assert(home != NULL); NCpathcanonical(home,&globalstate->home); nullfree(home); } /* Capture $CWD */ { char cwdbuf[4096]; cwdbuf[0] = '\0'; (void)NCgetcwd(cwdbuf,sizeof(cwdbuf)); if(strlen(cwdbuf) == 0) { /* use tempdir */ strcpy(cwdbuf, globalstate->tempdir); } globalstate->cwd = strdup(cwdbuf); } ncloginit(); /* Now load RC Files */ ncrc_initialize(); /* Compute type alignments */ NC_compute_alignments(); #if defined(NETCDF_ENABLE_BYTERANGE) || defined(NETCDF_ENABLE_DAP) || defined(NETCDF_ENABLE_DAP4) /* Initialize curl if it is being used */ { CURLcode cstat = curl_global_init(CURL_GLOBAL_ALL); if(cstat != CURLE_OK) status = NC_ECURL; } #endif return status; } int NCDISPATCH_finalize(void) { int status = NC_NOERR; #if defined(NETCDF_ENABLE_BYTERANGE) || defined(NETCDF_ENABLE_DAP) || defined(NETCDF_ENABLE_DAP4) curl_global_cleanup(); #endif #if defined(NETCDF_ENABLE_DAP4) ncxml_finalize(); #endif NC_freeglobalstate(); /* should be one of the last things done */ return status; } /**************************************************/ /* Global State constants and state */ /* The singleton global state object */ static NCglobalstate* nc_globalstate = NULL; /* Forward */ static int NC_createglobalstate(void); /** \defgroup global_state Global state functions. */ /** \{ \ingroup global state */ /* NCglobal state management */ static int NC_createglobalstate(void) { int stat = NC_NOERR; const char* tmp = NULL; if(nc_globalstate == NULL) { nc_globalstate = calloc(1,sizeof(NCglobalstate)); } /* Initialize struct pointers */ if((nc_globalstate->rcinfo = calloc(1,sizeof(struct NCRCinfo)))==NULL) {stat = NC_ENOMEM; goto done;} if((nc_globalstate->rcinfo->entries = nclistnew())==NULL) {stat = NC_ENOMEM; goto done;} if((nc_globalstate->rcinfo->s3profiles = nclistnew())==NULL) {stat = NC_ENOMEM; goto done;} /* Get environment variables */ if(getenv(NCRCENVIGNORE) != NULL) nc_globalstate->rcinfo->ignore = 1; tmp = getenv(NCRCENVRC); if(tmp != NULL && strlen(tmp) > 0) nc_globalstate->rcinfo->rcfile = strdup(tmp); /* Initialize chunk cache defaults */ nc_globalstate->chunkcache.size = DEFAULT_CHUNK_CACHE_SIZE; /**< Default chunk cache size. */ nc_globalstate->chunkcache.nelems = DEFAULT_CHUNKS_IN_CACHE; /**< Default chunk cache number of elements. */ nc_globalstate->chunkcache.preemption = DEFAULT_CHUNK_CACHE_PREEMPTION; /**< Default chunk cache preemption. */ done: return stat; } /* Get global state */ NCglobalstate* NC_getglobalstate(void) { if(nc_globalstate == NULL) NC_createglobalstate(); return nc_globalstate; } void NC_freeglobalstate(void) { if(nc_globalstate != NULL) { nullfree(nc_globalstate->tempdir); nullfree(nc_globalstate->home); nullfree(nc_globalstate->cwd); nullfree(nc_globalstate->aws.default_region); nullfree(nc_globalstate->aws.config_file); nullfree(nc_globalstate->aws.profile); nullfree(nc_globalstate->aws.access_key_id); nullfree(nc_globalstate->aws.secret_access_key); if(nc_globalstate->rcinfo) { NC_rcclear(nc_globalstate->rcinfo); free(nc_globalstate->rcinfo); } free(nc_globalstate); nc_globalstate = NULL; } } /** \} */ /**************************************************/ /** \defgroup atomic_types Atomic Type functions */ /** \{ \ingroup atomic_types */ /* The sizes of types may vary from platform to platform, but within * netCDF files, type sizes are fixed. */ #define NC_CHAR_LEN sizeof(char) /**< @internal Size of char. */ #define NC_STRING_LEN sizeof(char *) /**< @internal Size of char *. */ #define NC_BYTE_LEN 1 /**< @internal Size of byte. */ #define NC_SHORT_LEN 2 /**< @internal Size of short. */ #define NC_INT_LEN 4 /**< @internal Size of int. */ #define NC_FLOAT_LEN 4 /**< @internal Size of float. */ #define NC_DOUBLE_LEN 8 /**< @internal Size of double. */ #define NC_INT64_LEN 8 /**< @internal Size of int64. */ /** @internal Names of atomic types. */ const char* nc4_atomic_name[NUM_ATOMIC_TYPES] = {"none", "byte", "char", "short", "int", "float", "double", "ubyte", "ushort", "uint", "int64", "uint64", "string"}; static const size_t nc4_atomic_size[NUM_ATOMIC_TYPES] = {0, NC_BYTE_LEN, NC_CHAR_LEN, NC_SHORT_LEN, NC_INT_LEN, NC_FLOAT_LEN, NC_DOUBLE_LEN, NC_BYTE_LEN, NC_SHORT_LEN, NC_INT_LEN, NC_INT64_LEN, NC_INT64_LEN, NC_STRING_LEN}; /** * @internal Get the name and size of an atomic type. For strings, 1 is * returned. * * @param typeid1 Type ID. * @param name Gets the name of the type. * @param size Gets the size of one element of the type in bytes. * * @return ::NC_NOERR No error. * @return ::NC_EBADID Bad ncid. * @return ::NC_EBADTYPE Type not found. * @author Dennis Heimbigner */ int NC4_inq_atomic_type(nc_type typeid1, char *name, size_t *size) { if (typeid1 >= NUM_ATOMIC_TYPES) return NC_EBADTYPE; if (name) strcpy(name, nc4_atomic_name[typeid1]); if (size) *size = nc4_atomic_size[typeid1]; return NC_NOERR; } /** * @internal Get the id and size of an atomic type by name. * * @param name [in] the name of the type. * @param idp [out] the type index of the type. * @param sizep [out] the size of one element of the type in bytes. * * @return ::NC_NOERR No error. * @return ::NC_EBADID Bad ncid. * @return ::NC_EBADTYPE Type not found. * @author Dennis Heimbigner */ int NC4_lookup_atomic_type(const char *name, nc_type* idp, size_t *sizep) { int i; if (name == NULL || strlen(name) == 0) return NC_EBADTYPE; for(i=0;ialignment.threshold = threshold; gs->alignment.alignment = alignment; gs->alignment.defined = 1; return NC_NOERR; } /** Provide get function to retrieve global data alignment information. The nc_get_alignment function return the last values set by nc_set_alignment. If nc_set_alignment has not been called, then it returns the value 0 for both threshold and alignment. @param thresholdp Return the current minimum size to which alignment is applied or zero. @param alignmentp Return the current alignment value or zero. @return ::NC_NOERR No error. @return ::NC_EINVAL Invalid input. @author Dennis Heimbigner @ingroup datasets */ int nc_get_alignment(int* thresholdp, int* alignmentp) { NCglobalstate* gs = NC_getglobalstate(); if(thresholdp) *thresholdp = gs->alignment.threshold; if(alignmentp) *alignmentp = gs->alignment.alignment; return NC_NOERR; } /** \} */