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