Coverage Report

Created: 2023-05-28 06:42

/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
    /* Ok, try to read superblock */
146
0
    if((stat = ncz_read_superblock(file,&nczarr_version,&zarr_format))) goto done;
147
148
0
    if(nczarr_version == NULL) /* default */
149
0
        nczarr_version = strdup(NCZARRVERSION);
150
0
    if(zarr_format == NULL) /* default */
151
0
       zarr_format = strdup(ZARRVERSION);
152
    /* Extract the information from it */
153
0
    if(sscanf(zarr_format,"%d",&zinfo->zarr.zarr_version)!=1)
154
0
  {stat = NC_ENCZARR; goto done;}   
155
0
    if(sscanf(nczarr_version,"%lu.%lu.%lu",
156
0
        &zinfo->zarr.nczarr_version.major,
157
0
        &zinfo->zarr.nczarr_version.minor,
158
0
        &zinfo->zarr.nczarr_version.release) == 0)
159
0
  {stat = NC_ENCZARR; goto done;}
160
161
    /* Load auth info from rc file */
162
0
    if((stat = ncuriparse(nc->path,&uri))) goto done;
163
0
    if(uri) {
164
0
  if((stat = NC_authsetup(&zinfo->auth, uri)))
165
0
      goto done;
166
0
    }
167
168
0
done:
169
0
    nullfree(zarr_format);
170
0
    nullfree(nczarr_version);
171
0
    ncurifree(uri);
172
0
    nclistfreeall(modeargs);
173
0
    if(json) NCJreclaim(json);
174
0
    nullfree(content);
175
0
    return ZUNTRACE(stat);
176
0
}
177
178
/**
179
 * @internal Determine whether file is netCDF-4.
180
 *
181
 * For libzarr, this is always true.
182
 *
183
 * @param h5 Pointer to HDF5 file info struct.
184
 *
185
 * @returns NC_NOERR No error.
186
 * @author Dennis Heimbigner.
187
 */
188
int
189
NCZ_isnetcdf4(struct NC_FILE_INFO* h5)
190
0
{
191
0
    int isnc4 = 1;
192
0
    NC_UNUSED(h5);
193
0
    return isnc4;
194
0
}
195
196
/**
197
 * @internal Determine version info
198
 *
199
 * For libzarr, this is not well defined
200
 *
201
 * @param majorp Pointer to major version number
202
 * @param minorp Pointer to minor version number
203
 * @param releasep Pointer to release version number
204
 *
205
 * @returns NC_NOERR No error.
206
 * @author Dennis Heimbigner.
207
 */
208
int
209
NCZ_get_libversion(unsigned long* majorp, unsigned long* minorp,unsigned long* releasep)
210
1
{
211
1
    unsigned long m0,m1,m2;
212
1
    sscanf(NCZARRVERSION,"%lu.%lu.%lu",&m0,&m1,&m2);
213
1
    if(majorp) *majorp = m0;
214
1
    if(minorp) *minorp = m1;
215
1
    if(releasep) *releasep = m2;
216
1
    return NC_NOERR;
217
1
}
218
219
/**
220
 * @internal Determine "superblock" number.
221
 *
222
 * For libzarr, use the value of the major part of the nczarr version.
223
 *
224
 * @param superblocp Pointer to place to return superblock.
225
 * use the nczarr format version major as the superblock number.
226
 *
227
 * @returns NC_NOERR No error.
228
 * @author Dennis Heimbigner.
229
 */
230
int
231
NCZ_get_superblock(NC_FILE_INFO_T* file, int* superblockp)
232
0
{
233
0
    NCZ_FILE_INFO_T* zinfo = file->format_file_info;
234
0
    if(superblockp) *superblockp = zinfo->zarr.nczarr_version.major;
235
0
    return NC_NOERR;
236
0
}
237
238
/**************************************************/
239
/* Utilities */
240
241
#if 0
242
/**
243
@internal Open the root group object
244
@param dataset - [in] the root dataset object
245
@param rootp - [out] created root group
246
@return NC_NOERR
247
@author Dennis Heimbigner
248
*/
249
static int
250
ncz_open_rootgroup(NC_FILE_INFO_T* dataset)
251
{
252
    int stat = NC_NOERR;
253
    int i;
254
    NCZ_FILE_INFO_T* zfile = NULL;
255
    NC_GRP_INFO_T* root = NULL;
256
    void* content = NULL;
257
    char* rootpath = NULL;
258
    NCjson* json = NULL;
259
260
    ZTRACE(3,"dataset=",dataset->hdr.name);
261
262
    zfile = dataset->format_file_info;
263
264
    /* Root should already be defined */
265
    root = dataset->root_grp;
266
267
    assert(root != NULL);
268
269
    if((stat=nczm_concat(NULL,ZGROUP,&rootpath)))
270
  goto done;
271
    if((stat = NCZ_downloadjson(zfile->map, rootpath, &json)))
272
  goto  done;
273
    /* Process the json */ 
274
    for(i=0;i<nclistlength(json->contents);i+=2) {
275
  const NCjson* key = nclistget(json->contents,i);
276
  const NCjson* value = nclistget(json->contents,i+1);
277
  if(strcmp(NCJstring(key),"zarr_format")==0) {
278
      int zversion;
279
      if(sscanf(NCJstring(value),"%d",&zversion)!=1)
280
    {stat = NC_ENOTNC; goto done;}    
281
      /* Verify against the dataset */
282
      if(zversion != zfile->zarr.zarr_version)
283
    {stat = NC_ENOTNC; goto done;}
284
  }
285
    }
286
287
done:
288
    if(json) NCJreclaim(json);
289
    nullfree(rootpath);
290
    nullfree(content);
291
    return ZUNTRACE(stat);
292
}
293
#endif
294
295
296
static const char*
297
controllookup(const char** envv_controls, const char* key)
298
0
{
299
0
    const char** p;
300
0
    for(p=envv_controls;*p;p+=2) {
301
0
  if(strcasecmp(key,*p)==0) {
302
0
      return p[1];
303
0
  }
304
0
    }
305
0
    return NULL;
306
0
}
307
308
309
static int
310
applycontrols(NCZ_FILE_INFO_T* zinfo)
311
0
{
312
0
    int i,stat = NC_NOERR;
313
0
    const char* value = NULL;
314
0
    NClist* modelist = nclistnew();
315
0
    int noflags = 0; /* track non-default negative flags */
316
317
0
    if((value = controllookup((const char**)zinfo->envv_controls,"mode")) != NULL) {
318
0
  if((stat = NCZ_comma_parse(value,modelist))) goto done;
319
0
    }
320
    /* Process the modelist first */
321
0
    zinfo->controls.mapimpl = NCZM_DEFAULT;
322
0
    zinfo->controls.flags |= FLAG_XARRAYDIMS; /* Always support XArray convention where possible */
323
0
    for(i=0;i<nclistlength(modelist);i++) {
324
0
        const char* p = nclistget(modelist,i);
325
0
  if(strcasecmp(p,PUREZARRCONTROL)==0)
326
0
      zinfo->controls.flags |= (FLAG_PUREZARR);
327
0
  else if(strcasecmp(p,XARRAYCONTROL)==0)
328
0
      zinfo->controls.flags |= FLAG_PUREZARR;
329
0
  else if(strcasecmp(p,NOXARRAYCONTROL)==0)
330
0
      noflags |= FLAG_XARRAYDIMS;
331
0
  else if(strcasecmp(p,"zip")==0) zinfo->controls.mapimpl = NCZM_ZIP;
332
0
  else if(strcasecmp(p,"file")==0) zinfo->controls.mapimpl = NCZM_FILE;
333
0
  else if(strcasecmp(p,"s3")==0) zinfo->controls.mapimpl = NCZM_S3;
334
0
    }
335
    /* Apply negative controls by turning off negative flags */
336
    /* This is necessary to avoid order dependence of mode flags when both positive and negative flags are defined */
337
0
    zinfo->controls.flags &= (~noflags);
338
339
    /* Process other controls */
340
0
    if((value = controllookup((const char**)zinfo->envv_controls,"log")) != NULL) {
341
0
  zinfo->controls.flags |= FLAG_LOGGING;
342
0
        ncsetlogging(1);
343
0
    }
344
0
    if((value = controllookup((const char**)zinfo->envv_controls,"show")) != NULL) {
345
0
  if(strcasecmp(value,"fetch")==0)
346
0
      zinfo->controls.flags |= FLAG_SHOWFETCH;
347
0
    }
348
0
done:
349
0
    nclistfreeall(modelist);
350
0
    return stat;
351
0
}
352
353
#if 0
354
/**
355
@internal Rewrite attributes into a group or var
356
@param map - [in] the map object for storage
357
@param container - [in] the containing object
358
@param jattrs - [in] the json for .zattrs
359
@param jtypes - [in] the json for .ztypes
360
@return NC_NOERR
361
@author Dennis Heimbigner
362
*/
363
int
364
ncz_unload_jatts(NCZ_FILE_INFO_T* zinfo, NC_OBJ* container, NCjson* jattrs, NCjson* jtypes)
365
{
366
    int stat = NC_NOERR;
367
    char* fullpath = NULL;
368
    char* akey = NULL;
369
    char* tkey = NULL;
370
    NCZMAP* map = zinfo->map;
371
372
    assert((NCJsort(jattrs) == NCJ_DICT));
373
    assert((NCJsort(jtypes) == NCJ_DICT));
374
375
    if(container->sort == NCGRP) {
376
        NC_GRP_INFO_T* grp = (NC_GRP_INFO_T*)container;
377
        /* Get grp's fullpath name */
378
        if((stat = NCZ_grpkey(grp,&fullpath)))
379
      goto done;
380
    } else {
381
        NC_VAR_INFO_T* var = (NC_VAR_INFO_T*)container;
382
        /* Get var's fullpath name */
383
        if((stat = NCZ_varkey(var,&fullpath)))
384
      goto done;
385
    }
386
387
    /* Construct the path to the .zattrs object */
388
    if((stat = nczm_concat(fullpath,ZATTRS,&akey)))
389
  goto done;
390
391
    /* Always write as V2 */
392
393
    {
394
        NCjson* k = NULL;
395
        NCjson* v = NULL;
396
  /* remove any previous version */
397
        if(!NCJremove(jattrs,NCZ_V2_ATTRS,1,&k,&v)) {
398
      NCJreclaim(k); NCJreclaim(v);
399
  }
400
    }
401
402
    if(!(zinfo->controls.flags & FLAG_PUREZARR)) {
403
        /* Insert the jtypes into the set of attributes */
404
         if((stat = NCJinsert(jattrs,NCZ_V2_ATTRS,jtypes))) goto done;
405
    }
406
407
    /* Upload the .zattrs object */
408
    if((stat=NCZ_uploadjson(map,tkey,jattrs)))
409
  goto done;
410
411
done:
412
    if(stat) {
413
  NCJreclaim(jattrs);
414
  NCJreclaim(jtypes);
415
    }
416
    nullfree(fullpath);
417
    nullfree(akey);
418
    nullfree(tkey);
419
    return stat;
420
}
421
#endif
422
423
424