Coverage Report

Created: 2025-10-28 07:06

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/netcdf-c/libnczarr/zclose.c
Line
Count
Source
1
/*********************************************************************
2
 *   Copyright 1993, UCAR/Unidata
3
 *   See netcdf/COPYRIGHT file for copying and redistribution conditions.
4
 *********************************************************************/
5
6
#include "zincludes.h"
7
#include "zfilter.h"
8
9
/* Forward */
10
static int zclose_group(NC_GRP_INFO_T*);
11
static int zclose_gatts(NC_GRP_INFO_T*);
12
static int zclose_vars(NC_GRP_INFO_T*);
13
static int zclose_dims(NC_GRP_INFO_T*);
14
static int zclose_types(NC_GRP_INFO_T*);
15
static int zclose_type(NC_TYPE_INFO_T* type);
16
static int zwrite_vars(NC_GRP_INFO_T *grp);
17
18
/**************************************************/
19
20
/**
21
 * @internal This function will recurse through an open ZARR file and
22
 * release resources. All ZARR annotations reclaimed
23
 *
24
 * @param file Pointer to ZARR file info struct.
25
 * @param abort True if this is an abort.
26
 *
27
 * @return ::NC_NOERR No error.
28
 * @return ::NC_ENCZARR could not close the file.
29
 * @author Dennis Heimbigner
30
 */
31
int
32
ncz_close_file(NC_FILE_INFO_T* file, int abort)
33
0
{
34
0
    int stat = NC_NOERR;
35
0
    NCZ_FILE_INFO_T* zinfo = NULL;
36
 
37
0
    ZTRACE(2,"file=%s abort=%d",file->hdr.name,abort);
38
39
0
    if(!abort) {
40
        /* Flush | create all chunks for all vars */
41
0
        if((stat=zwrite_vars(file->root_grp))) goto done;
42
0
    }
43
44
    /* Internal close to reclaim zarr annotations */
45
0
    if((stat = zclose_group(file->root_grp)))
46
0
  goto done;
47
48
0
    zinfo = file->format_file_info;
49
50
0
    if((stat = nczmap_close(zinfo->map,(abort && zinfo->creating)?1:0)))
51
0
  goto done;
52
0
    nclistfreeall(zinfo->controllist);
53
0
    NC_authfree(zinfo->auth);
54
0
    nullfree(zinfo);
55
56
0
done:
57
0
    return ZUNTRACE(stat);
58
0
}
59
60
/**************************************************/
61
/**
62
 * @internal Recursively free zarr annotations for a group (and everything
63
 * it contains).
64
 *
65
 * @param grp Pointer to group info struct.
66
 *
67
 * @return ::NC_NOERR No error.
68
 * @author Dennis Heimbigner
69
 */
70
static int
71
zclose_group(NC_GRP_INFO_T *grp)
72
0
{
73
0
    int stat = NC_NOERR;
74
0
    NCZ_GRP_INFO_T* zgrp;
75
0
    size_t i;
76
77
0
    assert(grp && grp->format_grp_info != NULL);
78
0
    LOG((3, "%s: grp->name %s", __func__, grp->hdr.name));
79
80
    /* Recursively call this function for each child, if any, stopping
81
     * if there is an error. */
82
0
    for(i=0; i<ncindexsize(grp->children); i++) {
83
0
        if ((stat = zclose_group((NC_GRP_INFO_T*)ncindexith(grp->children,i))))
84
0
            goto done;
85
0
    }
86
87
    /* Close resources associated with global attributes. */
88
0
    if ((stat = zclose_gatts(grp)))
89
0
        goto done;
90
91
    /* Close resources associated with vars. */
92
0
    if ((stat = zclose_vars(grp)))
93
0
        goto done;
94
95
    /* Close resources associated with dims. */
96
0
    if ((stat = zclose_dims(grp)))
97
0
        goto done;
98
99
    /* Close resources associated with types. */
100
0
    if ((stat = zclose_types(grp)))
101
0
        goto done;
102
103
    /* Close the zgroup. */
104
0
    zgrp = grp->format_grp_info;
105
0
    LOG((4, "%s: closing group %s", __func__, grp->hdr.name));
106
0
    nullfree(zgrp->zgroup.prefix);
107
0
    NCJreclaim(zgrp->zgroup.obj);
108
0
    NCJreclaim(zgrp->zgroup.atts);
109
0
    nullfree(zgrp);
110
0
    grp->format_grp_info = NULL; /* avoid memory errors */
111
112
0
done:
113
0
    return stat;
114
0
}
115
116
/**
117
 * @internal Close resources for global atts in a group.
118
 *
119
 * @param grp Pointer to group info struct.
120
 *
121
 * @return ::NC_NOERR No error.
122
 * @author Dennis Heimbigner
123
 */
124
static int
125
zclose_gatts(NC_GRP_INFO_T* grp)
126
0
{
127
0
    int stat = NC_NOERR;
128
0
    NC_ATT_INFO_T *att;
129
0
    size_t a;
130
0
    for(a = 0; a < ncindexsize(grp->att); a++) {
131
0
        NCZ_ATT_INFO_T* zatt = NULL;
132
0
        att = (NC_ATT_INFO_T* )ncindexith(grp->att, a);
133
0
        assert(att && att->format_att_info != NULL);
134
0
        zatt = att->format_att_info;
135
0
  nullfree(zatt);
136
0
        att->format_att_info = NULL; /* avoid memory errors */
137
0
    }
138
0
    return stat;
139
0
}
140
141
/**
142
 * @internal Close resources for single var
143
 *
144
 * @param var var to reclaim
145
 *
146
 * @return ::NC_NOERR No error.
147
 * @author Dennis Heimbigner
148
 */
149
int
150
NCZ_zclose_var1(NC_VAR_INFO_T* var)
151
0
{
152
0
    int stat = NC_NOERR;
153
0
    NCZ_VAR_INFO_T* zvar;
154
0
    NC_ATT_INFO_T* att;
155
0
    size_t a;
156
157
0
    assert(var && var->format_var_info);
158
0
    for(a = 0; a < ncindexsize(var->att); a++) {
159
0
  NCZ_ATT_INFO_T* zatt;
160
0
  att = (NC_ATT_INFO_T*)ncindexith(var->att, a);
161
0
  assert(att && att->format_att_info);
162
0
  zatt = att->format_att_info;
163
0
  nullfree(zatt);
164
0
  att->format_att_info = NULL; /* avoid memory errors */
165
0
    }
166
#ifdef NETCDF_ENABLE_NCZARR_FILTERS
167
    /* Reclaim filters */
168
    if(var->filters != NULL) {
169
  (void)NCZ_filter_freelists(var);
170
    }
171
    var->filters = NULL;
172
#endif
173
    /* Reclaim the type */
174
0
    if(var->type_info) (void)zclose_type(var->type_info);
175
    /* reclaim dispatch info */
176
0
    zvar = var->format_var_info;;
177
0
    if(zvar->cache) NCZ_free_chunk_cache(zvar->cache);
178
    /* reclaim xarray */
179
0
    if(zvar->xarray) nclistfreeall(zvar->xarray);
180
0
    nullfree(zvar->zarray.prefix);
181
0
    NCJreclaim(zvar->zarray.obj);
182
0
    NCJreclaim(zvar->zarray.atts);
183
0
    nullfree(zvar);
184
0
    var->format_var_info = NULL; /* avoid memory errors */
185
0
    return stat;
186
0
}
187
188
/**
189
 * @internal Close nczarr resources for vars in a group.
190
 *
191
 * @param grp Pointer to group info struct.
192
 *
193
 * @return ::NC_NOERR No error.
194
 * @author Dennis Heimbigner
195
 */
196
static int
197
zclose_vars(NC_GRP_INFO_T* grp)
198
0
{
199
0
    int stat = NC_NOERR;
200
0
    NC_VAR_INFO_T* var;
201
0
    size_t i;
202
203
0
    for(i = 0; i < ncindexsize(grp->vars); i++) {
204
0
        var = (NC_VAR_INFO_T*)ncindexith(grp->vars, i);
205
0
        assert(var && var->format_var_info);
206
0
  if((stat = NCZ_zclose_var1(var))) goto done;
207
0
    }
208
0
done:
209
0
    return stat;
210
0
}
211
212
/**
213
 * @internal Close resources for dims in a group.
214
 *
215
 * @param grp Pointer to group info struct.
216
 *
217
 * @return ::NC_NOERR No error.
218
 * @author Dennis Heimbigner
219
 */
220
static int
221
zclose_dims(NC_GRP_INFO_T* grp)
222
0
{
223
0
    int stat = NC_NOERR;
224
0
    NC_DIM_INFO_T* dim;
225
0
    size_t i;
226
227
0
    for(i = 0; i < ncindexsize(grp->dim); i++) {
228
0
        NCZ_DIM_INFO_T* zdim;
229
0
        dim = (NC_DIM_INFO_T*)ncindexith(grp->dim, i);
230
0
        assert(dim && dim->format_dim_info);
231
0
        zdim = dim->format_dim_info;
232
0
  nullfree(zdim);
233
0
  dim->format_dim_info = NULL; /* avoid memory errors */
234
0
    }
235
236
0
    return stat;
237
0
}
238
239
/**
240
 * @internal Close resources for a single type.  Set values to
241
 * 0 after closing types. Because of type reference counters, these
242
 * closes can be called multiple times.
243
 *
244
 * @param type Pointer to type struct.
245
 *
246
 * @return ::NC_NOERR No error.
247
 * @author Dennis Heimbigner
248
 */
249
static int
250
zclose_type(NC_TYPE_INFO_T* type)
251
0
{
252
0
    int stat = NC_NOERR;
253
254
0
    assert(type && type->format_type_info != NULL);
255
0
    nullfree(type->format_type_info);
256
0
    return stat;
257
0
}
258
259
/**
260
 * @internal Close resources for types in a group.  Set values to
261
 * 0 after closing types. Because of type reference counters, these
262
 * closes can be called multiple times.
263
 * Warning: note that atomic types are not covered here; this
264
 * is only for user-defined types.
265
 *
266
 * @param grp Pointer to group info struct.
267
 *
268
 * @return ::NC_NOERR No error.
269
 * @author Dennis Heimbigner
270
 */
271
static int
272
zclose_types(NC_GRP_INFO_T* grp)
273
0
{
274
0
    int stat = NC_NOERR;
275
0
    size_t i;
276
0
    NC_TYPE_INFO_T* type;
277
278
0
    for(i = 0; i < ncindexsize(grp->type); i++)
279
0
    {
280
0
        type = (NC_TYPE_INFO_T*)ncindexith(grp->type, i);
281
0
  if((stat = zclose_type(type))) goto done;
282
0
    }
283
0
done:
284
0
    return stat;
285
0
}
286
287
/**
288
 * @internal Recursively flush/create all data for all vars.
289
 *
290
 * @param grp Pointer to group info struct whose vars need to be written
291
 *
292
 * @return ::NC_NOERR No error.
293
 * @author Dennis Heimbigner
294
 */
295
static int
296
zwrite_vars(NC_GRP_INFO_T *grp)
297
0
{
298
0
    int stat = NC_NOERR;
299
0
    size_t i;
300
301
0
    assert(grp && grp->format_grp_info != NULL);
302
0
    LOG((3, "%s: grp->name %s", __func__, grp->hdr.name));
303
304
    /* Write all vars for this group breadth first */
305
0
    for(i = 0; i < ncindexsize(grp->vars); i++) {
306
0
        NC_VAR_INFO_T* var = (NC_VAR_INFO_T*)ncindexith(grp->vars, i);
307
0
  if((stat = ncz_write_var(var))) goto done;
308
0
    }
309
310
    /* Recursively call this function for each child group, if any, stopping
311
     * if there is an error. */
312
0
    for(i=0; i<ncindexsize(grp->children); i++) {
313
0
        if ((stat = zwrite_vars((NC_GRP_INFO_T*)ncindexith(grp->children,i))))
314
0
            goto done;
315
0
    }
316
317
0
done:
318
0
    return stat;
319
0
}
320
321