/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 | | |