/src/netcdf-c/libnczarr/zmetadata2.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 | | |
8 | 0 | #define MINIMIM_CSL_REP_RAW "{\"metadata\":{},\"zarr_consolidated_format\":1}" |
9 | | |
10 | | /// @brief Retrieve the group and variable names contained within a group specified by `key` on the storage. The order of the names may be arbitrary |
11 | | /// @param zfile - The zarr file info structure |
12 | | /// @param key - the key of the node - group |
13 | | /// @param groups - NClist where names will be added |
14 | | /// @param variables - NClist where names will be added |
15 | | /// @return `NC_NOERR` if succeeding |
16 | | int NCZMD_v2_list_nodes(NCZ_FILE_INFO_T *zfile, const char * key, NClist *groups, NClist *vars); |
17 | | |
18 | | /// @brief Retrieve the group and variable names contained within a group specified by `key` on the consolidated representation. The order of the names may be arbitrary |
19 | | /// @param zfile - The zarr file info structure |
20 | | /// @param key - the key of the node - group |
21 | | /// @param groups - NClist where names will be added |
22 | | /// @param variables - NClist where names will be added |
23 | | /// @return `NC_NOERR` if succeeding |
24 | | int NCZMD_v2_csl_list_nodes(NCZ_FILE_INFO_T *zfile, const char * key, NClist *groups, NClist *vars); |
25 | | |
26 | | /// @brief Retrieve the group names contained within a group specified by `key` on the storage. The order of the names may be arbitrary |
27 | | /// @param zfile - The zarr file info structure |
28 | | /// @param key - the key of the node - group |
29 | | /// @param groups - NClist where names will be added |
30 | | /// @return `NC_NOERR` if succeeding |
31 | | int NCZMD_v2_list_groups(NCZ_FILE_INFO_T *zfile, const char * key, NClist *groups); |
32 | | |
33 | | /// @brief Retrieve the group names contained within a group specified by `key` on the consolidated represention. The order of the names may be arbitrary |
34 | | /// @param zfile - The zarr file info structure |
35 | | /// @param key - the key of the node - group |
36 | | /// @param groups - NClist where names will be added |
37 | | /// @return `NC_NOERR` if succeeding |
38 | | int NCZMD_v2_csl_list_groups(NCZ_FILE_INFO_T *zfile, const char * key, NClist *groups); |
39 | | |
40 | | /// @brief Retrieve the variable names contained by a group specified by `key` on the storage. The order of the names may be arbitrary |
41 | | /// @param zfile - The zarr file info structure |
42 | | /// @param key - the key of the node - group |
43 | | /// @param variables - NClist where names will be added |
44 | | /// @return `NC_NOERR` if succeeding |
45 | | int NCZMD_v2_list_variables(NCZ_FILE_INFO_T *zfile, const char * key, NClist * variables); |
46 | | |
47 | | /// @brief Retrieve the variable names contained by a group specified by `key` on the consolidated representation. The order of the names may be arbitrary |
48 | | /// @param zfile - The zarr file info structure |
49 | | /// @param key - the key of the node - group |
50 | | /// @param variables - NClist where names will be added |
51 | | /// @return `NC_NOERR` if succeeding |
52 | | int NCZMD_v2_csl_list_variables(NCZ_FILE_INFO_T *zfile, const char * key, NClist *groups); |
53 | | |
54 | | /// @brief Retrieve JSON metadata of a given type for the specified `key` from the storage |
55 | | /// @param zfile - The zarr file info structure |
56 | | /// @param zobj - The type of metadata to set |
57 | | /// @param key - the key of the node - group or array |
58 | | /// @param jobj - JSON to be written |
59 | | /// @return `NC_NOERR` if succeeding |
60 | | int fetch_json_content_v2(NCZ_FILE_INFO_T *zfile, NCZMD_MetadataType zarr_obj_type, const char *key, NCjson **jobj); |
61 | | |
62 | | /// @brief Retrieve JSON metadata of a given type for the specified `key` from the consolidate representation |
63 | | /// @param zfile - The zarr file info structure |
64 | | /// @param zobj - The type of metadata to set |
65 | | /// @param key - the key of the node - group or array |
66 | | /// @param jobj - JSON to be written |
67 | | /// @return `NC_NOERR` if succeeding |
68 | | int fetch_csl_json_content_v2(NCZ_FILE_INFO_T *zfile, NCZMD_MetadataType zarr_obj_type, const char *key, NCjson **jobj); |
69 | | |
70 | | /// @brief Write JSON metadata of a given type for the specified `key` to the storage |
71 | | /// @param zfile - The zarr file info structure |
72 | | /// @param zobj - The type of metadata to set |
73 | | /// @param key - the key of the node - group or array |
74 | | /// @param jobj - JSON to be written |
75 | | /// @return `NC_NOERR` if succeeding |
76 | | int update_json_content_v2(NCZ_FILE_INFO_T *zfile, NCZMD_MetadataType zobj, const char *key, const NCjson *jobj); |
77 | | |
78 | | /// @brief Updates the JSON metadata of a given type for the specified `key` to the consolidated representation |
79 | | /// @param zfile - The zarr file info structure |
80 | | /// @param zobj - The type of metadata to set |
81 | | /// @param key - the key of the node - group or array |
82 | | /// @param jobj - JSON to be written |
83 | | /// @return `NC_NOERR` if succeeding |
84 | | int update_csl_json_content_v2(NCZ_FILE_INFO_T *zfile, NCZMD_MetadataType zobj, const char *key, const NCjson *jobj); |
85 | | |
86 | | /// @brief Place holder for non consolidated handler |
87 | | /// @param json - Not used! |
88 | | /// @return `NC_NOERR` always |
89 | | int validate_consolidated_json_noop_v2(const NCjson *json); |
90 | | |
91 | | ///@brief Checks if `json` is a compliant to what .zmetadata expects |
92 | | /// - non empty `{}` in "metadata" |
93 | | /// - `zarr_consolidated_format` exists and is `1` |
94 | | /// @param json corresponding to the full .zmetadata content |
95 | | /// @return `NC_NOERR` if valid, `NC_EZARRMETA` otherwise |
96 | | int validate_consolidated_json_v2(const NCjson *json); |
97 | | |
98 | | static const NCZ_Metadata NCZ_md2_table = { |
99 | | ZARRFORMAT2, |
100 | | NCZ_METADATA_VERSION, |
101 | | ZARR_NOT_CONSOLIDATED, |
102 | | .jcsl = NULL, |
103 | | |
104 | | .list_nodes = NCZMD_v2_list_nodes, |
105 | | .list_groups = NCZMD_v2_list_groups, |
106 | | .list_variables = NCZMD_v2_list_variables, |
107 | | |
108 | | .fetch_json_content = fetch_json_content_v2, |
109 | | .update_json_content = update_json_content_v2, |
110 | | .validate_consolidated = validate_consolidated_json_noop_v2, |
111 | | }; |
112 | | |
113 | | const NCZ_Metadata *NCZ_metadata_handler2 = &NCZ_md2_table; |
114 | | |
115 | | static const NCZ_Metadata NCZ_csl_md2_table = { |
116 | | ZARRFORMAT2, |
117 | | NCZ_METADATA_VERSION, |
118 | | ZARR_CONSOLIDATED, |
119 | | .jcsl = NULL, |
120 | | |
121 | | .list_nodes = NCZMD_v2_csl_list_nodes, |
122 | | .list_groups = NCZMD_v2_csl_list_groups, |
123 | | .list_variables = NCZMD_v2_csl_list_variables, |
124 | | |
125 | | .fetch_json_content = fetch_csl_json_content_v2, |
126 | | .update_json_content = update_csl_json_content_v2, |
127 | | .validate_consolidated = validate_consolidated_json_v2, |
128 | | }; |
129 | | |
130 | | const NCZ_Metadata *NCZ_csl_metadata_handler2 = &NCZ_csl_md2_table; |
131 | | |
132 | | int NCZMD_v2_list_nodes(NCZ_FILE_INFO_T *zfile, const char * key, NClist *groups, NClist *variables) |
133 | 0 | { |
134 | 0 | size_t i; |
135 | 0 | int stat = NC_NOERR; |
136 | 0 | char *subkey = NULL; |
137 | 0 | char *zkey = NULL; |
138 | 0 | NClist *matches = nclistnew(); |
139 | |
|
140 | 0 | if ((stat = nczmap_search(zfile->map, key, matches))) |
141 | 0 | goto done; |
142 | 0 | for (i = 0; i < nclistlength(matches); i++) |
143 | 0 | { |
144 | 0 | const char *name = nclistget(matches, i); |
145 | 0 | if (name[0] == NCZM_DOT) |
146 | 0 | continue; |
147 | 0 | if ((stat = nczm_concat(key, name, &subkey))) |
148 | 0 | goto done; |
149 | 0 | if ((stat = nczm_concat(subkey, Z2GROUP, &zkey))) |
150 | 0 | goto done; |
151 | 0 | if (NC_NOERR == nczmap_exists(zfile->map, zkey) && groups != NULL) |
152 | 0 | nclistpush(groups, strdup(name)); |
153 | |
|
154 | 0 | nullfree(zkey); |
155 | 0 | zkey = NULL; |
156 | 0 | if ((stat = nczm_concat(subkey, Z2ARRAY, &zkey))) |
157 | 0 | goto done; |
158 | 0 | if (NC_NOERR == nczmap_exists(zfile->map, zkey) && variables != NULL) |
159 | 0 | nclistpush(variables, strdup(name)); |
160 | 0 | stat = NC_NOERR; |
161 | |
|
162 | 0 | nullfree(subkey); |
163 | 0 | subkey = NULL; |
164 | 0 | nullfree(zkey); |
165 | 0 | zkey = NULL; |
166 | 0 | } |
167 | | |
168 | 0 | done: |
169 | 0 | nullfree(subkey); |
170 | 0 | nullfree(zkey); |
171 | 0 | nclistfreeall(matches); |
172 | 0 | return stat; |
173 | 0 | } |
174 | | |
175 | | int NCZMD_v2_csl_list_nodes(NCZ_FILE_INFO_T *zfile, const char * key, NClist *groups, NClist *variables) |
176 | 0 | { |
177 | 0 | size_t i; |
178 | 0 | int stat = NC_NOERR; |
179 | 0 | char *subkey = NULL; |
180 | 0 | char *zgroup = NULL; |
181 | 0 | NClist *segments = nclistnew(); |
182 | |
|
183 | 0 | const char *group = key + (key[0] == '/'); |
184 | 0 | size_t lgroup = strlen(group); |
185 | |
|
186 | 0 | const NCjson *jmetadata = NULL; |
187 | 0 | NCJdictget(zfile->metadata.jcsl, "metadata", &jmetadata); |
188 | 0 | for (i = 0; i < NCJdictlength(jmetadata); i++) |
189 | 0 | { |
190 | 0 | NCjson *jname = NCJdictkey(jmetadata, i); |
191 | 0 | const char *fullname = NCJstring(jname); |
192 | 0 | size_t lfullname = strlen(fullname); |
193 | 0 | if (lfullname < lgroup || |
194 | 0 | strncmp(fullname, group, lgroup) || |
195 | 0 | (lgroup > 0 && fullname[lgroup] != NCZM_SEP[0])) |
196 | 0 | { |
197 | 0 | continue; |
198 | 0 | } |
199 | | |
200 | 0 | nclistclearall(segments); |
201 | 0 | NC_split_delim(fullname + lgroup + (lgroup > 0), NCZM_SEP[0] ,segments); |
202 | 0 | size_t slen = nclistlength(segments); |
203 | 0 | if (slen != 2) { |
204 | 0 | continue; |
205 | 0 | } |
206 | | |
207 | 0 | if (strncmp(Z2GROUP, nclistget(segments,1), sizeof(Z2GROUP)) == 0 && groups != NULL) |
208 | 0 | { |
209 | 0 | nclistpush(groups, strdup(nclistget(segments,0))); |
210 | 0 | } |
211 | 0 | else if (strncmp(Z2ARRAY, nclistget(segments,1), sizeof(Z2ARRAY)) == 0 && variables != NULL) |
212 | 0 | { |
213 | 0 | nclistpush(variables, strdup(nclistget(segments,0))); |
214 | 0 | } |
215 | 0 | } |
216 | 0 | nullfree(subkey); |
217 | 0 | nullfree(zgroup); |
218 | 0 | nclistfreeall(segments); |
219 | 0 | return stat; |
220 | 0 | } |
221 | | |
222 | | int NCZMD_v2_list_groups(NCZ_FILE_INFO_T *zfile, const char * key, NClist *groups) |
223 | 0 | { |
224 | 0 | return NCZMD_v2_list_nodes(zfile, key, groups, NULL); |
225 | 0 | } |
226 | | |
227 | | int NCZMD_v2_csl_list_groups(NCZ_FILE_INFO_T *zfile, const char * key, NClist *groups) |
228 | 0 | { |
229 | 0 | return NCZMD_v2_csl_list_nodes(zfile, key, groups, NULL); |
230 | 0 | } |
231 | | |
232 | | int NCZMD_v2_list_variables(NCZ_FILE_INFO_T *zfile, const char * key, NClist *variables) |
233 | 0 | { |
234 | 0 | return NCZMD_v2_list_nodes(zfile, key, NULL, variables); |
235 | 0 | } |
236 | | |
237 | | int NCZMD_v2_csl_list_variables(NCZ_FILE_INFO_T *zfile, const char* key, NClist *variables) |
238 | 0 | { |
239 | 0 | return NCZMD_v2_csl_list_nodes(zfile, key, NULL, variables); |
240 | 0 | } |
241 | | |
242 | 0 | static int zarr_obj_type2suffix(NCZMD_MetadataType zarr_obj_type, const char **suffix){ |
243 | 0 | switch (zarr_obj_type) |
244 | 0 | { |
245 | 0 | case NCZMD_GROUP: |
246 | 0 | *suffix = Z2GROUP; |
247 | 0 | break; |
248 | 0 | case NCZMD_ATTRS: |
249 | 0 | *suffix = Z2ATTRS; |
250 | 0 | break; |
251 | 0 | case NCZMD_ARRAY: |
252 | 0 | *suffix = Z2ARRAY; |
253 | 0 | break; |
254 | 0 | default: |
255 | 0 | return NC_EINVAL; |
256 | 0 | } |
257 | 0 | return NC_NOERR; |
258 | 0 | } |
259 | | |
260 | | int fetch_json_content_v2(NCZ_FILE_INFO_T *zfile, NCZMD_MetadataType zobj, const char *prefix, NCjson **jobj) |
261 | 0 | { |
262 | 0 | int stat = NC_NOERR; |
263 | 0 | const char *suffix; |
264 | 0 | char * key = NULL; |
265 | 0 | if ((stat = zarr_obj_type2suffix(zobj, &suffix)) |
266 | 0 | || (stat = nczm_concat(prefix, suffix, &key))){ |
267 | 0 | goto done; |
268 | 0 | } |
269 | | |
270 | 0 | stat = NCZ_downloadjson(zfile->map, key, jobj); |
271 | 0 | done: |
272 | 0 | nullfree(key); |
273 | 0 | return stat; |
274 | 0 | } |
275 | | |
276 | | int fetch_csl_json_content_v2(NCZ_FILE_INFO_T *zfile, NCZMD_MetadataType zobj_t, const char *prefix, NCjson **jobj) |
277 | 0 | { |
278 | 0 | int stat = NC_NOERR; |
279 | 0 | const NCjson *jtmp = NULL; |
280 | 0 | const char *suffix; |
281 | 0 | char * key = NULL; |
282 | 0 | if ( (stat = zarr_obj_type2suffix(zobj_t, &suffix)) |
283 | 0 | ||(stat = nczm_concat(prefix, suffix, &key))){ |
284 | 0 | return stat; |
285 | 0 | } |
286 | | |
287 | 0 | if (NCJdictget(zfile->metadata.jcsl, "metadata", &jtmp) == 0 |
288 | 0 | && jtmp && NCJsort(jtmp) == NCJ_DICT) |
289 | 0 | { |
290 | 0 | NCjson *tmp = NULL; |
291 | 0 | if ((stat = NCJdictget(jtmp, key + (key[0] == '/'), (const NCjson**)&tmp))) |
292 | 0 | goto done; |
293 | 0 | if (tmp) |
294 | 0 | NCJclone(tmp, jobj); |
295 | 0 | } |
296 | 0 | done: |
297 | 0 | nullfree(key); |
298 | 0 | return stat; |
299 | |
|
300 | 0 | } |
301 | | |
302 | | int update_csl_json_content_v2(NCZ_FILE_INFO_T *zfile, NCZMD_MetadataType zobj_t, const char *prefix, const NCjson *jobj) |
303 | 0 | { |
304 | 0 | int stat = NC_NOERR; |
305 | |
|
306 | 0 | if ((stat=update_json_content_v2(zfile,zobj_t,prefix,jobj))){ |
307 | 0 | goto done; |
308 | 0 | } |
309 | 0 | if (zfile->metadata.jcsl == NULL && |
310 | 0 | (stat = NCJparse(MINIMIM_CSL_REP_RAW,0,&zfile->metadata.jcsl))){ |
311 | 0 | goto done; |
312 | 0 | } |
313 | | |
314 | 0 | NCjson * jrep = NULL; |
315 | 0 | if ((stat = NCJdictget(zfile->metadata.jcsl,"metadata", (const NCjson**)&jrep)) || jrep == NULL) { |
316 | 0 | goto done; |
317 | 0 | } |
318 | | |
319 | 0 | const char *suffix; |
320 | 0 | char * key = NULL; |
321 | 0 | if ((stat = zarr_obj_type2suffix(zobj_t, &suffix)) |
322 | 0 | || (stat = nczm_concat(prefix, suffix, &key))){ |
323 | 0 | goto done; |
324 | 0 | } |
325 | 0 | const char * mdkey= key[0] == '/'?key+1:key; |
326 | 0 | NCjson * jval = NULL; |
327 | 0 | NCJclone(jobj,&jval); |
328 | 0 | NCJinsert(jrep, mdkey, jval); |
329 | 0 | done: |
330 | 0 | free(key); |
331 | 0 | return stat; |
332 | |
|
333 | 0 | } |
334 | | int update_json_content_v2(NCZ_FILE_INFO_T *zfile, NCZMD_MetadataType zobj, const char *prefix, const NCjson *jobj) |
335 | 0 | { |
336 | 0 | int stat = NC_NOERR; |
337 | 0 | const char *suffix; |
338 | 0 | char * key = NULL; |
339 | 0 | if ((stat = zarr_obj_type2suffix(zobj, &suffix)) |
340 | 0 | || (stat = nczm_concat(prefix, suffix, &key))){ |
341 | 0 | goto done; |
342 | 0 | } |
343 | | |
344 | 0 | stat = NCZ_uploadjson(zfile->map, key, jobj); |
345 | 0 | done: |
346 | 0 | nullfree(key); |
347 | 0 | return stat; |
348 | 0 | } |
349 | | |
350 | 0 | int validate_consolidated_json_noop_v2(const NCjson *json){ |
351 | 0 | NC_UNUSED(json); |
352 | 0 | return NC_NOERR; |
353 | 0 | } |
354 | | |
355 | | int validate_consolidated_json_v2(const NCjson *json) |
356 | 0 | { |
357 | 0 | if (json == NULL || NCJsort(json) != NCJ_DICT || NCJdictlength(json) == 0) |
358 | 0 | return NC_EZARRMETA; |
359 | | |
360 | 0 | const NCjson *jtmp = NULL; |
361 | 0 | NCJdictget(json, "metadata", &jtmp); |
362 | 0 | if (jtmp == NULL || NCJsort(jtmp) != NCJ_DICT || NCJdictlength(jtmp) == 0) |
363 | 0 | return NC_EZARRMETA; |
364 | | |
365 | 0 | jtmp = NULL; |
366 | 0 | struct NCJconst format = {0,0,0,0}; |
367 | 0 | NCJdictget(json, "zarr_consolidated_format", &jtmp); |
368 | 0 | if (jtmp == NULL || NCJsort(jtmp) != NCJ_INT || NCJcvt(jtmp,NCJ_INT, &format ) || format.ival != 1) |
369 | 0 | return NC_EZARRMETA; |
370 | | |
371 | 0 | return NC_NOERR; |
372 | 0 | } |