Coverage Report

Created: 2026-01-04 06:24

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
    NCZMD_free_metadata_handler(&(zinfo->metadata));
55
0
    nullfree(zinfo);
56
57
0
done:
58
0
    return ZUNTRACE(stat);
59
0
}
60
61
/**************************************************/
62
/**
63
 * @internal Recursively free zarr annotations for a group (and everything
64
 * it contains).
65
 *
66
 * @param grp Pointer to group info struct.
67
 *
68
 * @return ::NC_NOERR No error.
69
 * @author Dennis Heimbigner
70
 */
71
static int
72
zclose_group(NC_GRP_INFO_T *grp)
73
0
{
74
0
    int stat = NC_NOERR;
75
0
    NCZ_GRP_INFO_T* zgrp;
76
0
    size_t i;
77
78
0
    assert(grp && grp->format_grp_info != NULL);
79
0
    LOG((3, "%s: grp->name %s", __func__, grp->hdr.name));
80
81
    /* Recursively call this function for each child, if any, stopping
82
     * if there is an error. */
83
0
    for(i=0; i<ncindexsize(grp->children); i++) {
84
0
        if ((stat = zclose_group((NC_GRP_INFO_T*)ncindexith(grp->children,i))))
85
0
            goto done;
86
0
    }
87
88
    /* Close resources associated with global attributes. */
89
0
    if ((stat = zclose_gatts(grp)))
90
0
        goto done;
91
92
    /* Close resources associated with vars. */
93
0
    if ((stat = zclose_vars(grp)))
94
0
        goto done;
95
96
    /* Close resources associated with dims. */
97
0
    if ((stat = zclose_dims(grp)))
98
0
        goto done;
99
100
    /* Close resources associated with types. */
101
0
    if ((stat = zclose_types(grp)))
102
0
        goto done;
103
104
    /* Close the zgroup. */
105
0
    zgrp = grp->format_grp_info;
106
0
    LOG((4, "%s: closing group %s", __func__, grp->hdr.name));
107
0
    nullfree(zgrp->zgroup.prefix);
108
0
    NCJreclaim(zgrp->zgroup.obj);
109
0
    NCJreclaim(zgrp->zgroup.atts);
110
0
    nullfree(zgrp);
111
0
    grp->format_grp_info = NULL; /* avoid memory errors */
112
113
0
done:
114
0
    return stat;
115
0
}
116
117
/**
118
 * @internal Close resources for global atts in a group.
119
 *
120
 * @param grp Pointer to group info struct.
121
 *
122
 * @return ::NC_NOERR No error.
123
 * @author Dennis Heimbigner
124
 */
125
static int
126
zclose_gatts(NC_GRP_INFO_T* grp)
127
0
{
128
0
    int stat = NC_NOERR;
129
0
    NC_ATT_INFO_T *att;
130
0
    size_t a;
131
0
    for(a = 0; a < ncindexsize(grp->att); a++) {
132
0
        NCZ_ATT_INFO_T* zatt = NULL;
133
0
        att = (NC_ATT_INFO_T* )ncindexith(grp->att, a);
134
0
        assert(att && att->format_att_info != NULL);
135
0
        zatt = att->format_att_info;
136
0
  nullfree(zatt);
137
0
        att->format_att_info = NULL; /* avoid memory errors */
138
0
    }
139
0
    return stat;
140
0
}
141
142
/**
143
 * @internal Close resources for single var
144
 *
145
 * @param var var to reclaim
146
 *
147
 * @return ::NC_NOERR No error.
148
 * @author Dennis Heimbigner
149
 */
150
int
151
NCZ_zclose_var1(NC_VAR_INFO_T* var)
152
0
{
153
0
    int stat = NC_NOERR;
154
0
    NCZ_VAR_INFO_T* zvar;
155
0
    NC_ATT_INFO_T* att;
156
0
    size_t a;
157
158
0
    assert(var && var->format_var_info);
159
0
    for(a = 0; a < ncindexsize(var->att); a++) {
160
0
  NCZ_ATT_INFO_T* zatt;
161
0
  att = (NC_ATT_INFO_T*)ncindexith(var->att, a);
162
0
  assert(att && att->format_att_info);
163
0
  zatt = att->format_att_info;
164
0
  nullfree(zatt);
165
0
  att->format_att_info = NULL; /* avoid memory errors */
166
0
    }
167
#ifdef NETCDF_ENABLE_NCZARR_FILTERS
168
    /* Reclaim filters */
169
    if(var->filters != NULL) {
170
  (void)NCZ_filter_freelists(var);
171
    }
172
    var->filters = NULL;
173
#endif
174
    /* Reclaim the type */
175
0
    if(var->type_info) (void)zclose_type(var->type_info);
176
    /* reclaim dispatch info */
177
0
    zvar = var->format_var_info;;
178
0
    if(zvar->cache) NCZ_free_chunk_cache(zvar->cache);
179
    /* reclaim xarray */
180
0
    if(zvar->xarray) nclistfreeall(zvar->xarray);
181
0
    nullfree(zvar->zarray.prefix);
182
0
    NCJreclaim(zvar->zarray.obj);
183
0
    NCJreclaim(zvar->zarray.atts);
184
0
    nullfree(zvar);
185
0
    var->format_var_info = NULL; /* avoid memory errors */
186
0
    return stat;
187
0
}
188
189
/**
190
 * @internal Close nczarr resources for vars in a group.
191
 *
192
 * @param grp Pointer to group info struct.
193
 *
194
 * @return ::NC_NOERR No error.
195
 * @author Dennis Heimbigner
196
 */
197
static int
198
zclose_vars(NC_GRP_INFO_T* grp)
199
0
{
200
0
    int stat = NC_NOERR;
201
0
    NC_VAR_INFO_T* var;
202
0
    size_t i;
203
204
0
    for(i = 0; i < ncindexsize(grp->vars); i++) {
205
0
        var = (NC_VAR_INFO_T*)ncindexith(grp->vars, i);
206
0
        assert(var && var->format_var_info);
207
0
  if((stat = NCZ_zclose_var1(var))) goto done;
208
0
    }
209
0
done:
210
0
    return stat;
211
0
}
212
213
/**
214
 * @internal Close resources for dims in a group.
215
 *
216
 * @param grp Pointer to group info struct.
217
 *
218
 * @return ::NC_NOERR No error.
219
 * @author Dennis Heimbigner
220
 */
221
static int
222
zclose_dims(NC_GRP_INFO_T* grp)
223
0
{
224
0
    int stat = NC_NOERR;
225
0
    NC_DIM_INFO_T* dim;
226
0
    size_t i;
227
228
0
    for(i = 0; i < ncindexsize(grp->dim); i++) {
229
0
        NCZ_DIM_INFO_T* zdim;
230
0
        dim = (NC_DIM_INFO_T*)ncindexith(grp->dim, i);
231
0
        assert(dim && dim->format_dim_info);
232
0
        zdim = dim->format_dim_info;
233
0
  nullfree(zdim);
234
0
  dim->format_dim_info = NULL; /* avoid memory errors */
235
0
    }
236
237
0
    return stat;
238
0
}
239
240
/**
241
 * @internal Close resources for a single type.  Set values to
242
 * 0 after closing types. Because of type reference counters, these
243
 * closes can be called multiple times.
244
 *
245
 * @param type Pointer to type struct.
246
 *
247
 * @return ::NC_NOERR No error.
248
 * @author Dennis Heimbigner
249
 */
250
static int
251
zclose_type(NC_TYPE_INFO_T* type)
252
0
{
253
0
    int stat = NC_NOERR;
254
255
0
    assert(type && type->format_type_info != NULL);
256
0
    nullfree(type->format_type_info);
257
0
    return stat;
258
0
}
259
260
/**
261
 * @internal Close resources for types in a group.  Set values to
262
 * 0 after closing types. Because of type reference counters, these
263
 * closes can be called multiple times.
264
 * Warning: note that atomic types are not covered here; this
265
 * is only for user-defined types.
266
 *
267
 * @param grp Pointer to group info struct.
268
 *
269
 * @return ::NC_NOERR No error.
270
 * @author Dennis Heimbigner
271
 */
272
static int
273
zclose_types(NC_GRP_INFO_T* grp)
274
0
{
275
0
    int stat = NC_NOERR;
276
0
    size_t i;
277
0
    NC_TYPE_INFO_T* type;
278
279
0
    for(i = 0; i < ncindexsize(grp->type); i++)
280
0
    {
281
0
        type = (NC_TYPE_INFO_T*)ncindexith(grp->type, i);
282
0
  if((stat = zclose_type(type))) goto done;
283
0
    }
284
0
done:
285
0
    return stat;
286
0
}
287
288
/**
289
 * @internal Recursively flush/create all data for all vars.
290
 *
291
 * @param grp Pointer to group info struct whose vars need to be written
292
 *
293
 * @return ::NC_NOERR No error.
294
 * @author Dennis Heimbigner
295
 */
296
static int
297
zwrite_vars(NC_GRP_INFO_T *grp)
298
0
{
299
0
    int stat = NC_NOERR;
300
0
    size_t i;
301
302
0
    assert(grp && grp->format_grp_info != NULL);
303
0
    LOG((3, "%s: grp->name %s", __func__, grp->hdr.name));
304
305
    /* Write all vars for this group breadth first */
306
0
    for(i = 0; i < ncindexsize(grp->vars); i++) {
307
0
        NC_VAR_INFO_T* var = (NC_VAR_INFO_T*)ncindexith(grp->vars, i);
308
0
  if((stat = ncz_write_var(var))) goto done;
309
0
    }
310
311
    /* Recursively call this function for each child group, if any, stopping
312
     * if there is an error. */
313
0
    for(i=0; i<ncindexsize(grp->children); i++) {
314
0
        if ((stat = zwrite_vars((NC_GRP_INFO_T*)ncindexith(grp->children,i))))
315
0
            goto done;
316
0
    }
317
318
0
done:
319
0
    return stat;
320
0
}
321
322