/src/netcdf-c/libdispatch/ddispatch.c
Line | Count | Source |
1 | | /* |
2 | | Copyright (c) 1998-2018 University Corporation for Atmospheric Research/Unidata |
3 | | See LICENSE.txt for license information. |
4 | | */ |
5 | | |
6 | | #include "config.h" |
7 | | #include "ncdispatch.h" |
8 | | #include "ncuri.h" |
9 | | #include "nclog.h" |
10 | | #include "ncbytes.h" |
11 | | #include "ncrc.h" |
12 | | #include "ncoffsets.h" |
13 | | #include "ncpathmgr.h" |
14 | | #include "ncxml.h" |
15 | | #include "nc4internal.h" |
16 | | |
17 | | /* Required for getcwd, other functions. */ |
18 | | #ifdef HAVE_UNISTD_H |
19 | | #include <unistd.h> |
20 | | #endif |
21 | | |
22 | | /* Required for getcwd, other functions. */ |
23 | | #ifdef _WIN32 |
24 | | #include <direct.h> |
25 | | #endif |
26 | | |
27 | | #if defined(NETCDF_ENABLE_BYTERANGE) || defined(NETCDF_ENABLE_DAP) || defined(NETCDF_ENABLE_DAP4) |
28 | | #include <curl/curl.h> |
29 | | #endif |
30 | | |
31 | | #ifdef NETCDF_ENABLE_S3 |
32 | | #include "ncs3sdk.h" |
33 | | #endif |
34 | | |
35 | 0 | #define MAXPATH 1024 |
36 | | |
37 | | /* Define vectors of zeros and ones for use with various nc_get_varX functions */ |
38 | | /* Note, this form of initialization fails under Cygwin */ |
39 | | size_t NC_coord_zero[NC_MAX_VAR_DIMS] = {0}; |
40 | | size_t NC_coord_one[NC_MAX_VAR_DIMS] = {1}; |
41 | | ptrdiff_t NC_stride_one[NC_MAX_VAR_DIMS] = {1}; |
42 | | |
43 | | /* |
44 | | static nc_type longtype = (sizeof(long) == sizeof(int)?NC_INT:NC_INT64); |
45 | | static nc_type ulongtype = (sizeof(unsigned long) == sizeof(unsigned int)?NC_UINT:NC_UINT64); |
46 | | */ |
47 | | |
48 | | /* Allow dispatch to do general initialization and finalization */ |
49 | | int |
50 | | NCDISPATCH_initialize(void) |
51 | 1 | { |
52 | 1 | int status = NC_NOERR; |
53 | 1 | int i; |
54 | 1 | NCglobalstate* globalstate = NULL; |
55 | | |
56 | 1.02k | for(i=0;i<NC_MAX_VAR_DIMS;i++) { |
57 | 1.02k | NC_coord_zero[i] = 0; |
58 | 1.02k | NC_coord_one[i] = 1; |
59 | 1.02k | NC_stride_one[i] = 1; |
60 | 1.02k | } |
61 | | |
62 | 1 | globalstate = NC_getglobalstate(); /* will allocate and clear */ |
63 | | |
64 | | /* Capture temp dir*/ |
65 | 1 | { |
66 | 1 | char* tempdir = NULL; |
67 | | #if defined _WIN32 || defined __MSYS__ || defined __CYGWIN__ |
68 | | tempdir = getenv("TEMP"); |
69 | | #else |
70 | 1 | tempdir = "/tmp"; |
71 | 1 | #endif |
72 | 1 | if(tempdir == NULL) { |
73 | 0 | fprintf(stderr,"Cannot find a temp dir; using ./\n"); |
74 | 0 | tempdir = "."; |
75 | 0 | } |
76 | 1 | globalstate->tempdir= strdup(tempdir); |
77 | 1 | } |
78 | | |
79 | | /* Capture $HOME */ |
80 | 1 | { |
81 | | #if defined(_WIN32) && !defined(__MINGW32__) |
82 | | char* home = getenv("USERPROFILE"); |
83 | | #else |
84 | 1 | char* home = getenv("HOME"); |
85 | 1 | #endif |
86 | 1 | if(home == NULL) { |
87 | | /* use cwd */ |
88 | 0 | home = malloc(MAXPATH+1); |
89 | 0 | NCgetcwd(home,MAXPATH); |
90 | 0 | } else |
91 | 1 | home = strdup(home); /* make it always free'able */ |
92 | 1 | assert(home != NULL); |
93 | 1 | NCpathcanonical(home,&globalstate->home); |
94 | 1 | nullfree(home); |
95 | 1 | } |
96 | | |
97 | | /* Capture $CWD */ |
98 | 1 | { |
99 | 1 | char cwdbuf[4096]; |
100 | | |
101 | 1 | cwdbuf[0] = '\0'; |
102 | 1 | (void)NCgetcwd(cwdbuf,sizeof(cwdbuf)); |
103 | | |
104 | 1 | if(strlen(cwdbuf) == 0) { |
105 | | /* use tempdir */ |
106 | 0 | strcpy(cwdbuf, globalstate->tempdir); |
107 | 0 | } |
108 | 1 | globalstate->cwd = strdup(cwdbuf); |
109 | 1 | } |
110 | | |
111 | 1 | ncloginit(); |
112 | | |
113 | | /* Now load RC Files */ |
114 | 1 | ncrc_initialize(); |
115 | | |
116 | | /* Compute type alignments */ |
117 | 1 | NC_compute_alignments(); |
118 | | |
119 | | #if defined(NETCDF_ENABLE_BYTERANGE) || defined(NETCDF_ENABLE_DAP) || defined(NETCDF_ENABLE_DAP4) |
120 | | /* Initialize curl if it is being used */ |
121 | | { |
122 | | CURLcode cstat = curl_global_init(CURL_GLOBAL_ALL); |
123 | | if(cstat != CURLE_OK) |
124 | | status = NC_ECURL; |
125 | | } |
126 | | #endif |
127 | | |
128 | 1 | return status; |
129 | 1 | } |
130 | | |
131 | | int |
132 | | NCDISPATCH_finalize(void) |
133 | 1 | { |
134 | 1 | int status = NC_NOERR; |
135 | | #if defined(NETCDF_ENABLE_BYTERANGE) || defined(NETCDF_ENABLE_DAP) || defined(NETCDF_ENABLE_DAP4) |
136 | | curl_global_cleanup(); |
137 | | #endif |
138 | | #if defined(NETCDF_ENABLE_DAP4) |
139 | | ncxml_finalize(); |
140 | | #endif |
141 | 1 | NC_freeglobalstate(); /* should be one of the last things done */ |
142 | 1 | return status; |
143 | 1 | } |
144 | | |
145 | | /**************************************************/ |
146 | | /** \defgroup atomic_types Atomic Type functions */ |
147 | | /** \{ |
148 | | |
149 | | \ingroup atomic_types |
150 | | */ |
151 | | |
152 | | /* The sizes of types may vary from platform to platform, but within |
153 | | * netCDF files, type sizes are fixed. */ |
154 | | #define NC_CHAR_LEN sizeof(char) /**< @internal Size of char. */ |
155 | | #define NC_STRING_LEN sizeof(char *) /**< @internal Size of char *. */ |
156 | | #define NC_BYTE_LEN 1 /**< @internal Size of byte. */ |
157 | | #define NC_SHORT_LEN 2 /**< @internal Size of short. */ |
158 | | #define NC_INT_LEN 4 /**< @internal Size of int. */ |
159 | | #define NC_FLOAT_LEN 4 /**< @internal Size of float. */ |
160 | | #define NC_DOUBLE_LEN 8 /**< @internal Size of double. */ |
161 | | #define NC_INT64_LEN 8 /**< @internal Size of int64. */ |
162 | | |
163 | | /** @internal Names of atomic types. */ |
164 | | const char* nc4_atomic_name[NUM_ATOMIC_TYPES] = {"none", "byte", "char", |
165 | | "short", "int", "float", |
166 | | "double", "ubyte", |
167 | | "ushort", "uint", |
168 | | "int64", "uint64", "string"}; |
169 | | static const size_t nc4_atomic_size[NUM_ATOMIC_TYPES] = {0, NC_BYTE_LEN, NC_CHAR_LEN, NC_SHORT_LEN, |
170 | | NC_INT_LEN, NC_FLOAT_LEN, NC_DOUBLE_LEN, |
171 | | NC_BYTE_LEN, NC_SHORT_LEN, NC_INT_LEN, NC_INT64_LEN, |
172 | | NC_INT64_LEN, NC_STRING_LEN}; |
173 | | |
174 | | /** |
175 | | * @internal Get the name and size of an atomic type. For strings, 1 is |
176 | | * returned. |
177 | | * |
178 | | * @param typeid1 Type ID. |
179 | | * @param name Gets the name of the type. |
180 | | * @param size Gets the size of one element of the type in bytes. |
181 | | * |
182 | | * @return ::NC_NOERR No error. |
183 | | * @return ::NC_EBADID Bad ncid. |
184 | | * @return ::NC_EBADTYPE Type not found. |
185 | | * @author Dennis Heimbigner |
186 | | */ |
187 | | int |
188 | | NC4_inq_atomic_type(nc_type typeid1, char *name, size_t *size) |
189 | 0 | { |
190 | 0 | if (typeid1 >= NUM_ATOMIC_TYPES) |
191 | 0 | return NC_EBADTYPE; |
192 | 0 | if (name) |
193 | 0 | strcpy(name, nc4_atomic_name[typeid1]); |
194 | 0 | if (size) |
195 | 0 | *size = nc4_atomic_size[typeid1]; |
196 | 0 | return NC_NOERR; |
197 | 0 | } |
198 | | |
199 | | /** |
200 | | * @internal Get the id and size of an atomic type by name. |
201 | | * |
202 | | * @param name [in] the name of the type. |
203 | | * @param idp [out] the type index of the type. |
204 | | * @param sizep [out] the size of one element of the type in bytes. |
205 | | * |
206 | | * @return ::NC_NOERR No error. |
207 | | * @return ::NC_EBADID Bad ncid. |
208 | | * @return ::NC_EBADTYPE Type not found. |
209 | | * @author Dennis Heimbigner |
210 | | */ |
211 | | int |
212 | | NC4_lookup_atomic_type(const char *name, nc_type* idp, size_t *sizep) |
213 | 0 | { |
214 | 0 | int i; |
215 | |
|
216 | 0 | if (name == NULL || strlen(name) == 0) |
217 | 0 | return NC_EBADTYPE; |
218 | 0 | for(i=0;i<NUM_ATOMIC_TYPES;i++) { |
219 | 0 | if(strcasecmp(name,nc4_atomic_name[i])==0) { |
220 | 0 | if(idp) *idp = i; |
221 | 0 | if(sizep) *sizep = nc4_atomic_size[i]; |
222 | 0 | return NC_NOERR; |
223 | 0 | } |
224 | 0 | } |
225 | 0 | return NC_EBADTYPE; |
226 | 0 | } |
227 | | |
228 | | /** |
229 | | * @internal Get the id of an atomic type from the name. |
230 | | * |
231 | | * @param ncid File and group ID. |
232 | | * @param name Name of type |
233 | | * @param typeidp Pointer that will get the type ID. |
234 | | * |
235 | | * @return ::NC_NOERR No error. |
236 | | * @return ::NC_EBADTYPE Type not found. |
237 | | * @author Ed Hartnett |
238 | | */ |
239 | | int |
240 | | NC4_inq_atomic_typeid(int ncid, const char *name, nc_type *typeidp) |
241 | 0 | { |
242 | 0 | int i; |
243 | |
|
244 | 0 | NC_UNUSED(ncid); |
245 | | |
246 | | /* Handle atomic types. */ |
247 | 0 | for (i = 0; i < NUM_ATOMIC_TYPES; i++) { |
248 | 0 | if (!strcmp(name, nc4_atomic_name[i])) |
249 | 0 | { |
250 | 0 | if (typeidp) |
251 | 0 | *typeidp = i; |
252 | 0 | return NC_NOERR; |
253 | 0 | } |
254 | 0 | } |
255 | 0 | return NC_EBADTYPE; |
256 | 0 | } |
257 | | |
258 | | /** |
259 | | * @internal Get the class of a type |
260 | | * |
261 | | * @param xtype NetCDF type ID. |
262 | | * @param type_class Pointer that gets class of type, NC_INT, |
263 | | * NC_FLOAT, NC_CHAR, or NC_STRING, NC_ENUM, NC_VLEN, NC_COMPOUND, or |
264 | | * NC_OPAQUE. |
265 | | * |
266 | | * @return ::NC_NOERR No error. |
267 | | * @author Ed Hartnett, Dennis Heimbigner |
268 | | */ |
269 | | int |
270 | | NC4_get_atomic_typeclass(nc_type xtype, int *type_class) |
271 | 0 | { |
272 | 0 | assert(type_class); |
273 | 0 | switch (xtype) { |
274 | 0 | case NC_BYTE: |
275 | 0 | case NC_UBYTE: |
276 | 0 | case NC_SHORT: |
277 | 0 | case NC_USHORT: |
278 | 0 | case NC_INT: |
279 | 0 | case NC_UINT: |
280 | 0 | case NC_INT64: |
281 | 0 | case NC_UINT64: |
282 | | /* NC_INT is class used for all integral types */ |
283 | 0 | *type_class = NC_INT; |
284 | 0 | break; |
285 | 0 | case NC_FLOAT: |
286 | 0 | case NC_DOUBLE: |
287 | | /* NC_FLOAT is class used for all floating-point types */ |
288 | 0 | *type_class = NC_FLOAT; |
289 | 0 | break; |
290 | 0 | case NC_CHAR: |
291 | 0 | *type_class = NC_CHAR; |
292 | 0 | break; |
293 | 0 | case NC_STRING: |
294 | 0 | *type_class = NC_STRING; |
295 | 0 | break; |
296 | 0 | default: |
297 | 0 | return NC_EBADTYPE; |
298 | 0 | } |
299 | 0 | return NC_NOERR; |
300 | 0 | } |
301 | | |
302 | | /** \} */ |
303 | | |
304 | | /**************************************************/ |
305 | | /** \defgroup alignment Alignment functions. */ |
306 | | |
307 | | /** \{ |
308 | | |
309 | | \ingroup alignment |
310 | | */ |
311 | | |
312 | | /** |
313 | | Provide a function to store global data alignment |
314 | | information. |
315 | | Repeated calls to nc_set_alignment will overwrite any existing values. |
316 | | |
317 | | If defined, then for every file created or opened after the call to |
318 | | nc_set_alignment, and for every new variable added to the file, the |
319 | | most recently set threshold and alignment values will be applied |
320 | | to that variable. |
321 | | |
322 | | The nc_set_alignment function causes new data written to a |
323 | | netCDF-4 file to be aligned on disk to a specified block |
324 | | size. To be effective, alignment should be the system disk block |
325 | | size, or a multiple of it. This setting is effective with MPI |
326 | | I/O and other parallel systems. |
327 | | |
328 | | This is a trade-off of write speed versus file size. Alignment |
329 | | leaves holes between file objects. The default of no alignment |
330 | | writes file objects contiguously, without holes. Alignment has |
331 | | no impact on file readability. |
332 | | |
333 | | Alignment settings apply only indirectly, through the file open |
334 | | functions. Call nc_set_alignment first, then nc_create or |
335 | | nc_open for one or more files. Current alignment settings are |
336 | | locked in when each file is opened, then forgotten when the same |
337 | | file is closed. For illustration, it is possible to write |
338 | | different files at the same time with different alignments, by |
339 | | interleaving nc_set_alignment and nc_open calls. |
340 | | |
341 | | Alignment applies to all newly written low-level file objects at |
342 | | or above the threshold size, including chunks of variables, |
343 | | attributes, and internal infrastructure. Alignment is not locked |
344 | | in to a data variable. It can change between data chunks of the |
345 | | same variable, based on a file's history. |
346 | | |
347 | | Refer to H5Pset_alignment in HDF5 documentation for more |
348 | | specific details, interactions, and additional rules. |
349 | | |
350 | | @param threshold The minimum size to which alignment is applied. |
351 | | @param alignment The alignment value. |
352 | | |
353 | | @return ::NC_NOERR No error. |
354 | | @return ::NC_EINVAL Invalid input. |
355 | | @author Dennis Heimbigner |
356 | | @ingroup datasets |
357 | | */ |
358 | | int |
359 | | nc_set_alignment(int threshold, int alignment) |
360 | 0 | { |
361 | 0 | NCglobalstate* gs = NC_getglobalstate(); |
362 | 0 | gs->alignment.threshold = threshold; |
363 | 0 | gs->alignment.alignment = alignment; |
364 | 0 | gs->alignment.defined = 1; |
365 | 0 | return NC_NOERR; |
366 | 0 | } |
367 | | |
368 | | /** |
369 | | Provide get function to retrieve global data alignment |
370 | | information. |
371 | | |
372 | | The nc_get_alignment function return the last values set by |
373 | | nc_set_alignment. If nc_set_alignment has not been called, then |
374 | | it returns the value 0 for both threshold and alignment. |
375 | | |
376 | | @param thresholdp Return the current minimum size to which alignment is applied or zero. |
377 | | @param alignmentp Return the current alignment value or zero. |
378 | | |
379 | | @return ::NC_NOERR No error. |
380 | | @return ::NC_EINVAL Invalid input. |
381 | | @author Dennis Heimbigner |
382 | | @ingroup datasets |
383 | | */ |
384 | | |
385 | | int |
386 | | nc_get_alignment(int* thresholdp, int* alignmentp) |
387 | 0 | { |
388 | 0 | NCglobalstate* gs = NC_getglobalstate(); |
389 | 0 | if(thresholdp) *thresholdp = gs->alignment.threshold; |
390 | 0 | if(alignmentp) *alignmentp = gs->alignment.alignment; |
391 | 0 | return NC_NOERR; |
392 | 0 | } |
393 | | |
394 | | /** \} */ |