Coverage Report

Created: 2026-01-04 06:24

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}