Coverage Report

Created: 2022-11-18 06:58

/src/netcdf-c/libnczarr/zarr.c
Line
Count
Source (jump to first uncovered line)
1
/*********************************************************************
2
 *   Copyright 2018, UCAR/Unidata
3
 *   See netcdf/COPYRIGHT file for copying and redistribution conditions.
4
 *********************************************************************/
5
6
#include "zincludes.h"
7
8
/**************************************************/
9
/* Forwards */
10
11
static int applycontrols(NCZ_FILE_INFO_T* zinfo);
12
13
/***************************************************/
14
/* API */
15
16
/**
17
@internal Create the topmost dataset object and setup up
18
          NCZ_FILE_INFO_T state.
19
@param zinfo - [in] the internal state
20
@return NC_NOERR
21
@author Dennis Heimbigner
22
*/
23
24
int
25
ncz_create_dataset(NC_FILE_INFO_T* file, NC_GRP_INFO_T* root, const char** controls)
26
0
{
27
0
    int stat = NC_NOERR;
28
0
    NCZ_FILE_INFO_T* zinfo = NULL;
29
0
    NCZ_GRP_INFO_T* zgrp = NULL;
30
0
    NCURI* uri = NULL;
31
0
    NC* nc = NULL;
32
0
    NCjson* json = NULL;
33
0
    char* key = NULL;
34
35
0
    ZTRACE(3,"file=%s root=%s controls=%s",file->hdr.name,root->hdr.name,(controls?nczprint_envv(controls):"null"));
36
37
0
    nc = (NC*)file->controller;
38
39
    /* Add struct to hold NCZ-specific file metadata. */
40
0
    if (!(zinfo = calloc(1, sizeof(NCZ_FILE_INFO_T))))
41
0
        {stat = NC_ENOMEM; goto done;}
42
0
    file->format_file_info = zinfo;
43
0
    zinfo->common.file = file;
44
45
    /* Add struct to hold NCZ-specific group info. */
46
0
    if (!(zgrp = calloc(1, sizeof(NCZ_GRP_INFO_T))))
47
0
        {stat = NC_ENOMEM; goto done;}
48
0
    root->format_grp_info = zgrp;
49
0
    zgrp->common.file = file;
50
51
    /* Fill in NCZ_FILE_INFO_T */
52
0
    zinfo->created = 1;
53
0
    zinfo->common.file = file;
54
0
    zinfo->native_endianness = (NCZ_isLittleEndian() ? NC_ENDIAN_LITTLE : NC_ENDIAN_BIG);
55
0
    if((zinfo->envv_controls=NCZ_clonestringvec(0,controls)) == NULL)
56
0
  {stat = NC_ENOMEM; goto done;}
57
58
    /* fill in some of the zinfo and zroot fields */
59
0
    zinfo->zarr.zarr_version = atoi(ZARRVERSION);
60
0
    sscanf(NCZARRVERSION,"%lu.%lu.%lu",
61
0
     &zinfo->zarr.nczarr_version.major,
62
0
     &zinfo->zarr.nczarr_version.minor,
63
0
     &zinfo->zarr.nczarr_version.release);
64
65
0
    zinfo->default_maxstrlen = NCZ_MAXSTR_DEFAULT;
66
67
    /* Apply client controls */
68
0
    if((stat = applycontrols(zinfo))) goto done;
69
70
    /* Load auth info from rc file */
71
0
    if((stat = ncuriparse(nc->path,&uri))) goto done;
72
0
    if(uri) {
73
0
  if((stat = NC_authsetup(&zinfo->auth, uri)))
74
0
      goto done;
75
0
    }
76
77
    /* initialize map handle*/
78
0
    if((stat = nczmap_create(zinfo->controls.mapimpl,nc->path,nc->mode,zinfo->controls.flags,NULL,&zinfo->map)))
79
0
  goto done;
80
81
0
done:
82
0
    ncurifree(uri);
83
0
    NCJreclaim(json);
84
0
    nullfree(key);
85
0
    return ZUNTRACE(stat);
86
0
}
87
88
/**
89
@internal Open the topmost dataset object.
90
@param file - [in] the file struct
91
@param controls - [in] the fragment list in envv form from uri
92
@return NC_NOERR
93
@author Dennis Heimbigner
94
*/
95
96
int
97
ncz_open_dataset(NC_FILE_INFO_T* file, const char** controls)
98
0
{
99
0
    int stat = NC_NOERR;
100
0
    NC* nc = NULL;
101
0
    NC_GRP_INFO_T* root = NULL;
102
0
    NCURI* uri = NULL;
103
0
    void* content = NULL;
104
0
    NCjson* json = NULL;
105
0
    NCZ_FILE_INFO_T* zinfo = NULL;
106
0
    int mode;
107
0
    NClist* modeargs = NULL;
108
0
    char* nczarr_version = NULL;
109
0
    char* zarr_format = NULL;
110
111
0
    ZTRACE(3,"file=%s controls=%s",file->hdr.name,(controls?nczprint_envv(controls):"null"));
112
113
    /* Extract info reachable via file */
114
0
    nc = (NC*)file->controller;
115
0
    mode = nc->mode;
116
117
0
    root = file->root_grp;
118
0
    assert(root != NULL && root->hdr.sort == NCGRP);
119
120
    /* Add struct to hold NCZ-specific file metadata. */
121
0
    if (!(file->format_file_info = calloc(1, sizeof(NCZ_FILE_INFO_T))))
122
0
        {stat = NC_ENOMEM; goto done;}
123
0
    zinfo = file->format_file_info;
124
125
    /* Fill in NCZ_FILE_INFO_T */
126
0
    zinfo->created = 0;
127
0
    zinfo->common.file = file;
128
0
    zinfo->native_endianness = (NCZ_isLittleEndian() ? NC_ENDIAN_LITTLE : NC_ENDIAN_BIG);
129
0
    if((zinfo->envv_controls = NCZ_clonestringvec(0,controls))==NULL) /*0=>envv style*/
130
0
  {stat = NC_ENOMEM; goto done;}
131
0
    zinfo->default_maxstrlen = NCZ_MAXSTR_DEFAULT;
132
133
    /* Add struct to hold NCZ-specific group info. */
134
0
    if (!(root->format_grp_info = calloc(1, sizeof(NCZ_GRP_INFO_T))))
135
0
        {stat = NC_ENOMEM; goto done;}
136
0
    ((NCZ_GRP_INFO_T*)root->format_grp_info)->common.file = file;
137
138
    /* Apply client controls */
139
0
    if((stat = applycontrols(zinfo))) goto done;
140
141
    /* initialize map handle*/
142
0
    if((stat = nczmap_open(zinfo->controls.mapimpl,nc->path,mode,zinfo->controls.flags,NULL,&zinfo->map)))
143
0
  goto done;
144
145
0
    if((stat = ncz_read_superblock(file,&nczarr_version,&zarr_format))) goto done;
146
147
0
    if(nczarr_version == NULL) /* default */
148
0
        nczarr_version = strdup(NCZARRVERSION);
149
0
    if(zarr_format == NULL) /* default */
150
0
       zarr_format = strdup(ZARRVERSION);
151
    /* Extract the information from it */
152
0
    if(sscanf(zarr_format,"%d",&zinfo->zarr.zarr_version)!=1)
153
0
  {stat = NC_ENCZARR; goto done;}   
154
0
    if(sscanf(nczarr_version,"%lu.%lu.%lu",
155
0
        &zinfo->zarr.nczarr_version.major,
156
0
        &zinfo->zarr.nczarr_version.minor,
157
0
        &zinfo->zarr.nczarr_version.release) == 0)
158
0
  {stat = NC_ENCZARR; goto done;}
159
160
    /* Load auth info from rc file */
161
0
    if((stat = ncuriparse(nc->path,&uri))) goto done;
162
0
    if(uri) {
163
0
  if((stat = NC_authsetup(&zinfo->auth, uri)))
164
0
      goto done;
165
0
    }
166
167
0
done:
168
0
    nullfree(zarr_format);
169
0
    nullfree(nczarr_version);
170
0
    ncurifree(uri);
171
0
    nclistfreeall(modeargs);
172
0
    if(json) NCJreclaim(json);
173
0
    nullfree(content);
174
0
    return ZUNTRACE(stat);
175
0
}
176
177
/**
178
 * @internal Determine whether file is netCDF-4.
179
 *
180
 * For libzarr, this is always true.
181
 *
182
 * @param h5 Pointer to HDF5 file info struct.
183
 *
184
 * @returns NC_NOERR No error.
185
 * @author Dennis Heimbigner.
186
 */
187
int
188
NCZ_isnetcdf4(struct NC_FILE_INFO* h5)
189
0
{
190
0
    int isnc4 = 1;
191
0
    NC_UNUSED(h5);
192
0
    return isnc4;
193
0
}
194
195
/**
196
 * @internal Determine version info
197
 *
198
 * For libzarr, this is not well defined
199
 *
200
 * @param majorp Pointer to major version number
201
 * @param minorp Pointer to minor version number
202
 * @param releasep Pointer to release version number
203
 *
204
 * @returns NC_NOERR No error.
205
 * @author Dennis Heimbigner.
206
 */
207
int
208
NCZ_get_libversion(unsigned long* majorp, unsigned long* minorp,unsigned long* releasep)
209
1
{
210
1
    unsigned long m0,m1,m2;
211
1
    sscanf(NCZARRVERSION,"%lu.%lu.%lu",&m0,&m1,&m2);
212
1
    if(majorp) *majorp = m0;
213
1
    if(minorp) *minorp = m1;
214
1
    if(releasep) *releasep = m2;
215
1
    return NC_NOERR;
216
1
}
217
218
/**
219
 * @internal Determine "superblock" number.
220
 *
221
 * For libzarr, use the value of the major part of the nczarr version.
222
 *
223
 * @param superblocp Pointer to place to return superblock.
224
 * use the nczarr format version major as the superblock number.
225
 *
226
 * @returns NC_NOERR No error.
227
 * @author Dennis Heimbigner.
228
 */
229
int
230
NCZ_get_superblock(NC_FILE_INFO_T* file, int* superblockp)
231
0
{
232
0
    NCZ_FILE_INFO_T* zinfo = file->format_file_info;
233
0
    if(superblockp) *superblockp = zinfo->zarr.nczarr_version.major;
234
0
    return NC_NOERR;
235
0
}
236
237
/**************************************************/
238
/* Utilities */
239
240
#if 0
241
/**
242
@internal Open the root group object
243
@param dataset - [in] the root dataset object
244
@param rootp - [out] created root group
245
@return NC_NOERR
246
@author Dennis Heimbigner
247
*/
248
static int
249
ncz_open_rootgroup(NC_FILE_INFO_T* dataset)
250
{
251
    int stat = NC_NOERR;
252
    int i;
253
    NCZ_FILE_INFO_T* zfile = NULL;
254
    NC_GRP_INFO_T* root = NULL;
255
    void* content = NULL;
256
    char* rootpath = NULL;
257
    NCjson* json = NULL;
258
259
    ZTRACE(3,"dataset=",dataset->hdr.name);
260
261
    zfile = dataset->format_file_info;
262
263
    /* Root should already be defined */
264
    root = dataset->root_grp;
265
266
    assert(root != NULL);
267
268
    if((stat=nczm_concat(NULL,ZGROUP,&rootpath)))
269
  goto done;
270
    if((stat = NCZ_downloadjson(zfile->map, rootpath, &json)))
271
  goto  done;
272
    /* Process the json */ 
273
    for(i=0;i<nclistlength(json->contents);i+=2) {
274
  const NCjson* key = nclistget(json->contents,i);
275
  const NCjson* value = nclistget(json->contents,i+1);
276
  if(strcmp(NCJstring(key),"zarr_format")==0) {
277
      int zversion;
278
      if(sscanf(NCJstring(value),"%d",&zversion)!=1)
279
    {stat = NC_ENOTNC; goto done;}    
280
      /* Verify against the dataset */
281
      if(zversion != zfile->zarr.zarr_version)
282
    {stat = NC_ENOTNC; goto done;}
283
  }
284
    }
285
286
done:
287
    if(json) NCJreclaim(json);
288
    nullfree(rootpath);
289
    nullfree(content);
290
    return ZUNTRACE(stat);
291
}
292
#endif
293
294
295
static const char*
296
controllookup(const char** envv_controls, const char* key)
297
0
{
298
0
    const char** p;
299
0
    for(p=envv_controls;*p;p+=2) {
300
0
  if(strcasecmp(key,*p)==0) {
301
0
      return p[1];
302
0
  }
303
0
    }
304
0
    return NULL;
305
0
}
306
307
308
static int
309
applycontrols(NCZ_FILE_INFO_T* zinfo)
310
0
{
311
0
    int i,stat = NC_NOERR;
312
0
    const char* value = NULL;
313
0
    NClist* modelist = nclistnew();
314
0
    int noflags = 0; /* track non-default negative flags */
315
316
0
    if((value = controllookup((const char**)zinfo->envv_controls,"mode")) != NULL) {
317
0
  if((stat = NCZ_comma_parse(value,modelist))) goto done;
318
0
    }
319
    /* Process the modelist first */
320
0
    zinfo->controls.mapimpl = NCZM_DEFAULT;
321
0
    zinfo->controls.flags |= FLAG_XARRAYDIMS; /* Always support XArray convention where possible */
322
0
    for(i=0;i<nclistlength(modelist);i++) {
323
0
        const char* p = nclistget(modelist,i);
324
0
  if(strcasecmp(p,PUREZARRCONTROL)==0)
325
0
      zinfo->controls.flags |= (FLAG_PUREZARR);
326
0
  else if(strcasecmp(p,XARRAYCONTROL)==0)
327
0
      zinfo->controls.flags |= FLAG_PUREZARR;
328
0
  else if(strcasecmp(p,NOXARRAYCONTROL)==0)
329
0
      noflags |= FLAG_XARRAYDIMS;
330
0
  else if(strcasecmp(p,"zip")==0) zinfo->controls.mapimpl = NCZM_ZIP;
331
0
  else if(strcasecmp(p,"file")==0) zinfo->controls.mapimpl = NCZM_FILE;
332
0
  else if(strcasecmp(p,"s3")==0) zinfo->controls.mapimpl = NCZM_S3;
333
0
    }
334
    /* Apply negative controls by turning off negative flags */
335
    /* This is necessary to avoid order dependence of mode flags when both positive and negative flags are defined */
336
0
    zinfo->controls.flags &= (~noflags);
337
338
    /* Process other controls */
339
0
    if((value = controllookup((const char**)zinfo->envv_controls,"log")) != NULL) {
340
0
  zinfo->controls.flags |= FLAG_LOGGING;
341
0
        ncsetlogging(1);
342
0
    }
343
0
    if((value = controllookup((const char**)zinfo->envv_controls,"show")) != NULL) {
344
0
  if(strcasecmp(value,"fetch")==0)
345
0
      zinfo->controls.flags |= FLAG_SHOWFETCH;
346
0
    }
347
0
done:
348
0
    nclistfreeall(modelist);
349
0
    return stat;
350
0
}
351
352
#if 0
353
/**
354
@internal Rewrite attributes into a group or var
355
@param map - [in] the map object for storage
356
@param container - [in] the containing object
357
@param jattrs - [in] the json for .zattrs
358
@param jtypes - [in] the json for .ztypes
359
@return NC_NOERR
360
@author Dennis Heimbigner
361
*/
362
int
363
ncz_unload_jatts(NCZ_FILE_INFO_T* zinfo, NC_OBJ* container, NCjson* jattrs, NCjson* jtypes)
364
{
365
    int stat = NC_NOERR;
366
    char* fullpath = NULL;
367
    char* akey = NULL;
368
    char* tkey = NULL;
369
    NCZMAP* map = zinfo->map;
370
371
    assert((NCJsort(jattrs) == NCJ_DICT));
372
    assert((NCJsort(jtypes) == NCJ_DICT));
373
374
    if(container->sort == NCGRP) {
375
        NC_GRP_INFO_T* grp = (NC_GRP_INFO_T*)container;
376
        /* Get grp's fullpath name */
377
        if((stat = NCZ_grpkey(grp,&fullpath)))
378
      goto done;
379
    } else {
380
        NC_VAR_INFO_T* var = (NC_VAR_INFO_T*)container;
381
        /* Get var's fullpath name */
382
        if((stat = NCZ_varkey(var,&fullpath)))
383
      goto done;
384
    }
385
386
    /* Construct the path to the .zattrs object */
387
    if((stat = nczm_concat(fullpath,ZATTRS,&akey)))
388
  goto done;
389
390
    /* Always write as V2 */
391
392
    {
393
        NCjson* k = NULL;
394
        NCjson* v = NULL;
395
  /* remove any previous version */
396
        if(!NCJremove(jattrs,NCZ_V2_ATTRS,1,&k,&v)) {
397
      NCJreclaim(k); NCJreclaim(v);
398
  }
399
    }
400
401
    if(!(zinfo->controls.flags & FLAG_PUREZARR)) {
402
        /* Insert the jtypes into the set of attributes */
403
         if((stat = NCJinsert(jattrs,NCZ_V2_ATTRS,jtypes))) goto done;
404
    }
405
406
    /* Upload the .zattrs object */
407
    if((stat=NCZ_uploadjson(map,tkey,jattrs)))
408
  goto done;
409
410
done:
411
    if(stat) {
412
  NCJreclaim(jattrs);
413
  NCJreclaim(jtypes);
414
    }
415
    nullfree(fullpath);
416
    nullfree(akey);
417
    nullfree(tkey);
418
    return stat;
419
}
420
#endif
421
422
423