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