/src/netcdf-c/libnczarr/zarr.c
Line | Count | Source |
1 | | /********************************************************************* |
2 | | * Copyright 2018, UCAR/Unidata |
3 | | * See netcdf/COPYRIGHT file for copying and redistribution conditions. |
4 | | *********************************************************************/ |
5 | | |
6 | | #include "zincludes.h" |
7 | | #include <stddef.h> |
8 | | |
9 | | /**************************************************/ |
10 | | /* Forwards */ |
11 | | |
12 | | static int applycontrols(NCZ_FILE_INFO_T* zinfo); |
13 | | |
14 | | /***************************************************/ |
15 | | /* API */ |
16 | | |
17 | | /** |
18 | | @internal Create the topmost dataset object and setup up |
19 | | NCZ_FILE_INFO_T state. |
20 | | @param zinfo - [in] the internal state |
21 | | @return NC_NOERR |
22 | | @author Dennis Heimbigner |
23 | | */ |
24 | | |
25 | | int |
26 | | ncz_create_dataset(NC_FILE_INFO_T* file, NC_GRP_INFO_T* root, NClist* controls) |
27 | 0 | { |
28 | 0 | int stat = NC_NOERR; |
29 | 0 | NCZ_FILE_INFO_T* zinfo = NULL; |
30 | 0 | NCZ_GRP_INFO_T* zgrp = NULL; |
31 | 0 | NCURI* uri = NULL; |
32 | 0 | NC* nc = NULL; |
33 | 0 | NCjson* json = NULL; |
34 | 0 | char* key = NULL; |
35 | |
|
36 | 0 | ZTRACE(3,"file=%s root=%s controls=%s",file->hdr.name,root->hdr.name,(controls?nczprint_envv(controls):"null")); |
37 | |
|
38 | 0 | nc = (NC*)file->controller; |
39 | | |
40 | | /* Add struct to hold NCZ-specific file metadata. */ |
41 | 0 | if (!(zinfo = calloc(1, sizeof(NCZ_FILE_INFO_T)))) |
42 | 0 | {stat = NC_ENOMEM; goto done;} |
43 | 0 | file->format_file_info = zinfo; |
44 | 0 | zinfo->common.file = file; |
45 | | |
46 | | /* Add struct to hold NCZ-specific group info. */ |
47 | 0 | if (!(zgrp = calloc(1, sizeof(NCZ_GRP_INFO_T)))) |
48 | 0 | {stat = NC_ENOMEM; goto done;} |
49 | 0 | root->format_grp_info = zgrp; |
50 | 0 | zgrp->common.file = file; |
51 | | |
52 | | /* Fill in NCZ_FILE_INFO_T */ |
53 | 0 | zinfo->creating = 1; |
54 | 0 | zinfo->common.file = file; |
55 | 0 | zinfo->native_endianness = (NC_isLittleEndian() ? NC_ENDIAN_LITTLE : NC_ENDIAN_BIG); |
56 | 0 | if((zinfo->controllist=nclistclone(controls,1)) == NULL) |
57 | 0 | {stat = NC_ENOMEM; goto done;} |
58 | | |
59 | | /* fill in some of the zinfo and zroot fields */ |
60 | 0 | zinfo->format.zarr = ZARRFORMAT2; |
61 | 0 | zinfo->format.nczarr = NCZARRFORMAT2; |
62 | |
|
63 | 0 | zinfo->default_maxstrlen = NCZ_MAXSTR_DEFAULT; |
64 | | |
65 | | /* Apply client controls */ |
66 | 0 | if((stat = applycontrols(zinfo))) goto done; |
67 | | |
68 | | /* Load auth info from rc file */ |
69 | 0 | if((stat = ncuriparse(nc->path,&uri))) goto done; |
70 | 0 | if(uri) { |
71 | 0 | if((stat = NC_authsetup(&zinfo->auth, uri))) |
72 | 0 | goto done; |
73 | 0 | } |
74 | | |
75 | | /* initialize map handle*/ |
76 | 0 | if((stat = NCZ_get_map(file,uri,nc->mode,zinfo->controls.flags,NULL,&zinfo->map))){ |
77 | 0 | goto done; |
78 | 0 | } |
79 | | |
80 | 0 | if((stat = NCZMD_set_metadata_handler(zinfo))){ |
81 | 0 | goto done; |
82 | 0 | } |
83 | | |
84 | 0 | done: |
85 | 0 | ncurifree(uri); |
86 | 0 | NCJreclaim(json); |
87 | 0 | nullfree(key); |
88 | 0 | return ZUNTRACE(stat); |
89 | 0 | } |
90 | | |
91 | | /** |
92 | | @internal Open the topmost dataset object. |
93 | | @param file - [in] the file struct |
94 | | @param controls - [in] the fragment list in envv form from uri |
95 | | @return NC_NOERR |
96 | | @author Dennis Heimbigner |
97 | | */ |
98 | | |
99 | | int |
100 | | ncz_open_dataset(NC_FILE_INFO_T* file, NClist* controls) |
101 | 0 | { |
102 | 0 | int stat = NC_NOERR; |
103 | 0 | NC* nc = NULL; |
104 | 0 | NC_GRP_INFO_T* root = NULL; |
105 | 0 | NCURI* uri = NULL; |
106 | 0 | void* content = NULL; |
107 | 0 | NCjson* json = NULL; |
108 | 0 | NCZ_FILE_INFO_T* zinfo = NULL; |
109 | 0 | int mode; |
110 | 0 | NClist* modeargs = NULL; |
111 | 0 | char* nczarr_version = NULL; |
112 | 0 | char* zarr_format = NULL; |
113 | |
|
114 | 0 | ZTRACE(3,"file=%s controls=%s",file->hdr.name,(controls?nczprint_envv(controls):"null")); |
115 | | |
116 | | /* Extract info reachable via file */ |
117 | 0 | nc = (NC*)file->controller; |
118 | 0 | mode = nc->mode; |
119 | |
|
120 | 0 | root = file->root_grp; |
121 | 0 | assert(root != NULL && root->hdr.sort == NCGRP); |
122 | | |
123 | | /* Add struct to hold NCZ-specific file metadata. */ |
124 | 0 | if (!(file->format_file_info = calloc(1, sizeof(NCZ_FILE_INFO_T)))) |
125 | 0 | {stat = NC_ENOMEM; goto done;} |
126 | 0 | zinfo = file->format_file_info; |
127 | | |
128 | | /* Fill in NCZ_FILE_INFO_T */ |
129 | 0 | zinfo->creating = 0; |
130 | 0 | zinfo->common.file = file; |
131 | 0 | zinfo->native_endianness = (NC_isLittleEndian() ? NC_ENDIAN_LITTLE : NC_ENDIAN_BIG); |
132 | 0 | if((zinfo->controllist=nclistclone(controls,1)) == NULL) |
133 | 0 | {stat = NC_ENOMEM; goto done;} |
134 | 0 | zinfo->default_maxstrlen = NCZ_MAXSTR_DEFAULT; |
135 | | |
136 | | /* Add struct to hold NCZ-specific group info. */ |
137 | 0 | if (!(root->format_grp_info = calloc(1, sizeof(NCZ_GRP_INFO_T)))) |
138 | 0 | {stat = NC_ENOMEM; goto done;} |
139 | 0 | ((NCZ_GRP_INFO_T*)root->format_grp_info)->common.file = file; |
140 | | |
141 | | /* Apply client controls */ |
142 | 0 | if((stat = applycontrols(zinfo))) goto done; |
143 | | |
144 | | /* Load auth info from rc file */ |
145 | 0 | if((stat = ncuriparse(nc->path,&uri))) goto done; |
146 | 0 | if(uri) { |
147 | 0 | if((stat = NC_authsetup(&zinfo->auth, uri))) |
148 | 0 | goto done; |
149 | 0 | } |
150 | | |
151 | | /* initialize map handle*/ |
152 | 0 | if((stat = NCZ_get_map(file, uri, mode, zinfo->controls.flags,NULL,&zinfo->map))){ |
153 | 0 | goto done; |
154 | 0 | } |
155 | | |
156 | | /* Determine zarr format of existing dataset */ |
157 | 0 | if((stat = NCZ_infer_zarr_format(file))) { |
158 | 0 | goto done; |
159 | 0 | } |
160 | | |
161 | 0 | if((stat = NCZMD_set_metadata_handler(zinfo))) { |
162 | 0 | goto done; |
163 | 0 | } |
164 | | |
165 | 0 | if((stat = NCZ_infer_nczarr_format(file))) { |
166 | 0 | goto done; |
167 | 0 | } |
168 | | |
169 | 0 | done: |
170 | 0 | nullfree(zarr_format); |
171 | 0 | nullfree(nczarr_version); |
172 | 0 | ncurifree(uri); |
173 | 0 | nclistfreeall(modeargs); |
174 | 0 | if(json) NCJreclaim(json); |
175 | 0 | nullfree(content); |
176 | 0 | return ZUNTRACE(stat); |
177 | 0 | } |
178 | | |
179 | | /** |
180 | | * @internal Determine whether file is netCDF-4. |
181 | | * |
182 | | * For libzarr, this is always true. |
183 | | * |
184 | | * @param h5 Pointer to HDF5 file info struct. |
185 | | * |
186 | | * @returns NC_NOERR No error. |
187 | | * @author Dennis Heimbigner. |
188 | | */ |
189 | | int |
190 | | NCZ_isnetcdf4(struct NC_FILE_INFO* h5) |
191 | 0 | { |
192 | 0 | int isnc4 = 1; |
193 | 0 | NC_UNUSED(h5); |
194 | 0 | return isnc4; |
195 | 0 | } |
196 | | |
197 | | /** |
198 | | * @internal Determine version info |
199 | | * |
200 | | * For libzarr, this is not well defined |
201 | | * |
202 | | * @param majorp Pointer to major version number |
203 | | * @param minorp Pointer to minor version number |
204 | | * @param releasep Pointer to release version number |
205 | | * |
206 | | * @returns NC_NOERR No error. |
207 | | * @author Dennis Heimbigner. |
208 | | */ |
209 | | int |
210 | | NCZ_get_libversion(unsigned long* majorp, unsigned long* minorp,unsigned long* releasep) |
211 | 1 | { |
212 | 1 | unsigned long m0,m1,m2; |
213 | 1 | sscanf(NCZARR_PACKAGE_VERSION,"%lu.%lu.%lu",&m0,&m1,&m2); |
214 | 1 | if(majorp) *majorp = m0; |
215 | 1 | if(minorp) *minorp = m1; |
216 | 1 | if(releasep) *releasep = m2; |
217 | 1 | return NC_NOERR; |
218 | 1 | } |
219 | | |
220 | | /** |
221 | | * @internal Determine "superblock" number. |
222 | | * |
223 | | * For libzarr, use the value of the major part of the nczarr version. |
224 | | * |
225 | | * @param superblocp Pointer to place to return superblock. |
226 | | * use the nczarr format version major as the superblock number. |
227 | | * |
228 | | * @returns NC_NOERR No error. |
229 | | * @author Dennis Heimbigner. |
230 | | */ |
231 | | int |
232 | | NCZ_get_superblock(NC_FILE_INFO_T* file, int* superblockp) |
233 | 0 | { |
234 | 0 | NCZ_FILE_INFO_T* zinfo = file->format_file_info; |
235 | 0 | if(superblockp) *superblockp = zinfo->format.nczarr; |
236 | 0 | return NC_NOERR; |
237 | 0 | } |
238 | | |
239 | | /**************************************************/ |
240 | | /* Utilities */ |
241 | | |
242 | | static const char* |
243 | | controllookup(NClist* controls, const char* key) |
244 | 0 | { |
245 | 0 | size_t i; |
246 | 0 | for(i=0;i<nclistlength(controls);i+=2) { |
247 | 0 | const char* p = (char*)nclistget(controls,i); |
248 | 0 | if(strcasecmp(key,p)==0) { |
249 | 0 | return (const char*)nclistget(controls,i+1); |
250 | 0 | } |
251 | 0 | } |
252 | 0 | return NULL; |
253 | 0 | } |
254 | | |
255 | | |
256 | | static int |
257 | | applycontrols(NCZ_FILE_INFO_T* zinfo) |
258 | 0 | { |
259 | 0 | size_t i; |
260 | 0 | int stat = NC_NOERR; |
261 | 0 | const char* value = NULL; |
262 | 0 | NClist* modelist = nclistnew(); |
263 | 0 | size64_t noflags = 0; /* track non-default negative flags */ |
264 | |
|
265 | 0 | if((value = controllookup(zinfo->controllist,"mode")) != NULL) { |
266 | 0 | if((stat = NCZ_comma_parse(value,modelist))) goto done; |
267 | 0 | } |
268 | | /* Process the modelist first */ |
269 | 0 | zinfo->controls.mapimpl = NCZM_DEFAULT; |
270 | 0 | zinfo->controls.flags |= FLAG_XARRAYDIMS; /* Always support XArray convention where possible */ |
271 | 0 | zinfo->controls.flags |= (NCZARR_CONSOLIDATED_DEFAULT ? FLAG_CONSOLIDATED : 0); |
272 | 0 | for(i=0;i<nclistlength(modelist);i++) { |
273 | 0 | const char* p = nclistget(modelist,i); |
274 | 0 | if(strcasecmp(p,PUREZARRCONTROL)==0) |
275 | 0 | zinfo->controls.flags |= (FLAG_PUREZARR); |
276 | 0 | else if(strcasecmp(p,XARRAYCONTROL)==0) |
277 | 0 | zinfo->controls.flags |= FLAG_PUREZARR; |
278 | 0 | else if(strcasecmp(p,NOXARRAYCONTROL)==0) |
279 | 0 | noflags |= FLAG_XARRAYDIMS; |
280 | 0 | else if(strcasecmp(p,"zip")==0) zinfo->controls.mapimpl = NCZM_ZIP; |
281 | 0 | else if(strcasecmp(p,"file")==0) zinfo->controls.mapimpl = NCZM_FILE; |
282 | 0 | else if(strcasecmp(p,"s3")==0) zinfo->controls.mapimpl = NCZM_S3; |
283 | 0 | else if(strcasecmp(p,"consolidated") == 0) |
284 | 0 | zinfo->controls.flags |= FLAG_CONSOLIDATED; |
285 | 0 | } |
286 | | /* Apply negative controls by turning off negative flags */ |
287 | | /* This is necessary to avoid order dependence of mode flags when both positive and negative flags are defined */ |
288 | 0 | zinfo->controls.flags &= (~noflags); |
289 | | |
290 | | /* Process other controls */ |
291 | 0 | if((value = controllookup(zinfo->controllist,"log")) != NULL) { |
292 | 0 | zinfo->controls.flags |= FLAG_LOGGING; |
293 | 0 | ncsetloglevel(NCLOGNOTE); |
294 | 0 | } |
295 | 0 | if((value = controllookup(zinfo->controllist,"show")) != NULL) { |
296 | 0 | if(strcasecmp(value,"fetch")==0) |
297 | 0 | zinfo->controls.flags |= FLAG_SHOWFETCH; |
298 | 0 | } |
299 | 0 | done: |
300 | 0 | nclistfreeall(modelist); |
301 | 0 | return stat; |
302 | 0 | } |