/src/netcdf-c/libnczarr/zclose.c
Line | Count | Source (jump to first uncovered line) |
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->created)?1:0))) |
51 | 0 | goto done; |
52 | 0 | NCZ_freestringvec(0,zinfo->envv_controls); |
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 | int 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); |
107 | 0 | grp->format_grp_info = NULL; /* avoid memory errors */ |
108 | |
|
109 | 0 | done: |
110 | 0 | return stat; |
111 | 0 | } |
112 | | |
113 | | /** |
114 | | * @internal Close resources for global atts in a group. |
115 | | * |
116 | | * @param grp Pointer to group info struct. |
117 | | * |
118 | | * @return ::NC_NOERR No error. |
119 | | * @author Dennis Heimbigner |
120 | | */ |
121 | | static int |
122 | | zclose_gatts(NC_GRP_INFO_T* grp) |
123 | 0 | { |
124 | 0 | int stat = NC_NOERR; |
125 | 0 | NC_ATT_INFO_T *att; |
126 | 0 | int a; |
127 | 0 | for(a = 0; a < ncindexsize(grp->att); a++) { |
128 | 0 | NCZ_ATT_INFO_T* zatt = NULL; |
129 | 0 | att = (NC_ATT_INFO_T* )ncindexith(grp->att, a); |
130 | 0 | assert(att && att->format_att_info != NULL); |
131 | 0 | zatt = att->format_att_info; |
132 | 0 | nullfree(zatt); |
133 | 0 | att->format_att_info = NULL; /* avoid memory errors */ |
134 | 0 | } |
135 | 0 | return stat; |
136 | 0 | } |
137 | | |
138 | | /** |
139 | | * @internal Close resources for vars in a group. |
140 | | * |
141 | | * @param grp Pointer to group info struct. |
142 | | * |
143 | | * @return ::NC_NOERR No error. |
144 | | * @author Dennis Heimbigner |
145 | | */ |
146 | | static int |
147 | | zclose_vars(NC_GRP_INFO_T* grp) |
148 | 0 | { |
149 | 0 | int stat = NC_NOERR; |
150 | 0 | NC_VAR_INFO_T* var; |
151 | 0 | NCZ_VAR_INFO_T* zvar; |
152 | 0 | NC_ATT_INFO_T* att; |
153 | 0 | int a, i; |
154 | |
|
155 | 0 | for(i = 0; i < ncindexsize(grp->vars); i++) { |
156 | 0 | var = (NC_VAR_INFO_T*)ncindexith(grp->vars, i); |
157 | 0 | assert(var && var->format_var_info); |
158 | 0 | zvar = 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 | 0 | #ifdef ENABLE_NCZARR_FILTERS |
168 | | /* Reclaim filters */ |
169 | 0 | if(var->filters != NULL) { |
170 | 0 | (void)NCZ_filter_freelists(var); |
171 | 0 | } |
172 | 0 | var->filters = NULL; |
173 | 0 | #endif |
174 | | /* Reclaim the type */ |
175 | 0 | if(var->type_info) (void)zclose_type(var->type_info); |
176 | 0 | if(zvar->cache) NCZ_free_chunk_cache(zvar->cache); |
177 | | /* reclaim xarray */ |
178 | 0 | if(zvar->xarray) nclistfreeall(zvar->xarray); |
179 | 0 | nullfree(zvar); |
180 | 0 | var->format_var_info = NULL; /* avoid memory errors */ |
181 | 0 | } |
182 | 0 | return stat; |
183 | 0 | } |
184 | | |
185 | | /** |
186 | | * @internal Close resources for dims in a group. |
187 | | * |
188 | | * @param grp Pointer to group info struct. |
189 | | * |
190 | | * @return ::NC_NOERR No error. |
191 | | * @author Dennis Heimbigner |
192 | | */ |
193 | | static int |
194 | | zclose_dims(NC_GRP_INFO_T* grp) |
195 | 0 | { |
196 | 0 | int stat = NC_NOERR; |
197 | 0 | NC_DIM_INFO_T* dim; |
198 | 0 | int i; |
199 | |
|
200 | 0 | for(i = 0; i < ncindexsize(grp->dim); i++) { |
201 | 0 | NCZ_DIM_INFO_T* zdim; |
202 | 0 | dim = (NC_DIM_INFO_T*)ncindexith(grp->dim, i); |
203 | 0 | assert(dim && dim->format_dim_info); |
204 | 0 | zdim = dim->format_dim_info; |
205 | 0 | nullfree(zdim); |
206 | 0 | dim->format_dim_info = NULL; /* avoid memory errors */ |
207 | 0 | } |
208 | | |
209 | 0 | return stat; |
210 | 0 | } |
211 | | |
212 | | /** |
213 | | * @internal Close resources for a single type. Set values to |
214 | | * 0 after closing types. Because of type reference counters, these |
215 | | * closes can be called multiple times. |
216 | | * |
217 | | * @param type Pointer to type struct. |
218 | | * |
219 | | * @return ::NC_NOERR No error. |
220 | | * @author Dennis Heimbigner |
221 | | */ |
222 | | static int |
223 | | zclose_type(NC_TYPE_INFO_T* type) |
224 | 0 | { |
225 | 0 | int stat = NC_NOERR; |
226 | |
|
227 | 0 | assert(type && type->format_type_info != NULL); |
228 | 0 | nullfree(type->format_type_info); |
229 | 0 | return stat; |
230 | 0 | } |
231 | | |
232 | | /** |
233 | | * @internal Close resources for types in a group. Set values to |
234 | | * 0 after closing types. Because of type reference counters, these |
235 | | * closes can be called multiple times. |
236 | | * Warning: note that atomic types are not covered here; this |
237 | | * is only for user-defined types. |
238 | | * |
239 | | * @param grp Pointer to group info struct. |
240 | | * |
241 | | * @return ::NC_NOERR No error. |
242 | | * @author Dennis Heimbigner |
243 | | */ |
244 | | static int |
245 | | zclose_types(NC_GRP_INFO_T* grp) |
246 | 0 | { |
247 | 0 | int stat = NC_NOERR; |
248 | 0 | int i; |
249 | 0 | NC_TYPE_INFO_T* type; |
250 | |
|
251 | 0 | for(i = 0; i < ncindexsize(grp->type); i++) |
252 | 0 | { |
253 | 0 | type = (NC_TYPE_INFO_T*)ncindexith(grp->type, i); |
254 | 0 | if((stat = zclose_type(type))) goto done; |
255 | 0 | } |
256 | 0 | done: |
257 | 0 | return stat; |
258 | 0 | } |
259 | | |
260 | | /** |
261 | | * @internal Recursively flush/create all data for all vars. |
262 | | * |
263 | | * @param grp Pointer to group info struct whose vars need to be written |
264 | | * |
265 | | * @return ::NC_NOERR No error. |
266 | | * @author Dennis Heimbigner |
267 | | */ |
268 | | static int |
269 | | zwrite_vars(NC_GRP_INFO_T *grp) |
270 | 0 | { |
271 | 0 | int stat = NC_NOERR; |
272 | 0 | int i; |
273 | |
|
274 | 0 | assert(grp && grp->format_grp_info != NULL); |
275 | 0 | LOG((3, "%s: grp->name %s", __func__, grp->hdr.name)); |
276 | | |
277 | | /* Write all vars for this group breadth first */ |
278 | 0 | for(i = 0; i < ncindexsize(grp->vars); i++) { |
279 | 0 | NC_VAR_INFO_T* var = (NC_VAR_INFO_T*)ncindexith(grp->vars, i); |
280 | 0 | if((stat = ncz_write_var(var))) goto done; |
281 | 0 | } |
282 | | |
283 | | /* Recursively call this function for each child group, if any, stopping |
284 | | * if there is an error. */ |
285 | 0 | for(i=0; i<ncindexsize(grp->children); i++) { |
286 | 0 | if ((stat = zwrite_vars((NC_GRP_INFO_T*)ncindexith(grp->children,i)))) |
287 | 0 | goto done; |
288 | 0 | } |
289 | | |
290 | 0 | done: |
291 | 0 | return stat; |
292 | 0 | } |
293 | | |
294 | | |