/src/hdf5/src/H5Ocache_image.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
2 | | * Copyright by The HDF Group. * |
3 | | * All rights reserved. * |
4 | | * * |
5 | | * This file is part of HDF5. The full HDF5 copyright notice, including * |
6 | | * terms governing use, modification, and redistribution, is contained in * |
7 | | * the LICENSE file, which can be found at the root of the source code * |
8 | | * distribution tree, or in https://www.hdfgroup.org/licenses. * |
9 | | * If you do not have access to either file, you may request a copy from * |
10 | | * help@hdfgroup.org. * |
11 | | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ |
12 | | |
13 | | /*------------------------------------------------------------------------- |
14 | | * |
15 | | * Created: H5Ocache_image.c |
16 | | * |
17 | | * Purpose: A message indicating that a metadata cache image block |
18 | | * of the indicated length exists at the specified offset |
19 | | * in the HDF5 file. |
20 | | * |
21 | | * The mdci_msg only appears in the superblock extension |
22 | | * |
23 | | *------------------------------------------------------------------------- |
24 | | */ |
25 | | |
26 | | #include "H5Omodule.h" /* This source code file is part of the H5O module */ |
27 | | #define H5F_FRIEND /*suppress error about including H5Fpkg */ |
28 | | |
29 | | #include "H5private.h" /* Generic Functions */ |
30 | | #include "H5Eprivate.h" /* Error handling */ |
31 | | #include "H5Fpkg.h" /* Files */ |
32 | | #include "H5FLprivate.h" /* Free Lists */ |
33 | | #include "H5Opkg.h" /* Object headers */ |
34 | | #include "H5MFprivate.h" /* File space management */ |
35 | | |
36 | | /* Callbacks for message class */ |
37 | | static void *H5O__mdci_decode(H5F_t *f, H5O_t *open_oh, unsigned mesg_flags, unsigned *ioflags, size_t p_size, |
38 | | const uint8_t *p); |
39 | | static herr_t H5O__mdci_encode(H5F_t *f, bool disable_shared, size_t H5_ATTR_UNUSED p_size, uint8_t *p, |
40 | | const void *_mesg); |
41 | | static void *H5O__mdci_copy(const void *_mesg, void *_dest); |
42 | | static size_t H5O__mdci_size(const H5F_t *f, bool disable_shared, const void *_mesg); |
43 | | static herr_t H5O__mdci_free(void *mesg); |
44 | | static herr_t H5O__mdci_delete(H5F_t *f, H5O_t *open_oh, void *_mesg); |
45 | | static herr_t H5O__mdci_debug(H5F_t *f, const void *_mesg, FILE *stream, int indent, int fwidth); |
46 | | |
47 | | /* This message derives from H5O message class */ |
48 | | const H5O_msg_class_t H5O_MSG_MDCI[1] = {{ |
49 | | H5O_MDCI_MSG_ID, /* message id number */ |
50 | | "mdci", /* message name for debugging */ |
51 | | sizeof(H5O_mdci_t), /* native message size */ |
52 | | 0, /* messages are shareable? */ |
53 | | H5O__mdci_decode, /* decode message */ |
54 | | H5O__mdci_encode, /* encode message */ |
55 | | H5O__mdci_copy, /* copy method */ |
56 | | H5O__mdci_size, /* size of mdc image message */ |
57 | | NULL, /* reset method */ |
58 | | H5O__mdci_free, /* free method */ |
59 | | H5O__mdci_delete, /* file delete method */ |
60 | | NULL, /* link method */ |
61 | | NULL, /* set share method */ |
62 | | NULL, /* can share method */ |
63 | | NULL, /* pre copy native value to file */ |
64 | | NULL, /* copy native value to file */ |
65 | | NULL, /* post copy native value to file */ |
66 | | NULL, /* get creation index */ |
67 | | NULL, /* set creation index */ |
68 | | H5O__mdci_debug /* debugging */ |
69 | | }}; |
70 | | |
71 | | /* Only one version of the metadata cache image message at present */ |
72 | 0 | #define H5O_MDCI_VERSION_0 0 |
73 | | |
74 | | /* Declare the free list for H5O_mdci_t's */ |
75 | | H5FL_DEFINE_STATIC(H5O_mdci_t); |
76 | | |
77 | | /*------------------------------------------------------------------------- |
78 | | * Function: H5O__mdci_decode |
79 | | * |
80 | | * Purpose: Decode a metadata cache image message and return a |
81 | | * pointer to a newly allocated H5O_mdci_t struct. |
82 | | * |
83 | | * Return: Success: Pointer to new message in native struct |
84 | | * Failure: NULL |
85 | | *------------------------------------------------------------------------- |
86 | | */ |
87 | | static void * |
88 | | H5O__mdci_decode(H5F_t *f, H5O_t H5_ATTR_UNUSED *open_oh, unsigned H5_ATTR_UNUSED mesg_flags, |
89 | | unsigned H5_ATTR_UNUSED *ioflags, size_t p_size, const uint8_t *p) |
90 | 0 | { |
91 | 0 | H5O_mdci_t *mesg = NULL; /* New cache image message */ |
92 | 0 | const uint8_t *p_end = p + p_size - 1; /* End of the p buffer */ |
93 | 0 | void *ret_value = NULL; |
94 | |
|
95 | 0 | FUNC_ENTER_PACKAGE |
96 | |
|
97 | 0 | assert(f); |
98 | 0 | assert(p); |
99 | | |
100 | | /* Version of message */ |
101 | 0 | if (H5_IS_BUFFER_OVERFLOW(p, 1, p_end)) |
102 | 0 | HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "ran off end of input buffer while decoding"); |
103 | 0 | if (*p++ != H5O_MDCI_VERSION_0) |
104 | 0 | HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "bad version number for message"); |
105 | | |
106 | | /* Allocate space for message */ |
107 | 0 | if (NULL == (mesg = (H5O_mdci_t *)H5FL_MALLOC(H5O_mdci_t))) |
108 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, |
109 | 0 | "memory allocation failed for metadata cache image message"); |
110 | | |
111 | 0 | if (H5_IS_BUFFER_OVERFLOW(p, H5F_sizeof_addr(f), p_end)) |
112 | 0 | HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "ran off end of input buffer while decoding"); |
113 | 0 | H5F_addr_decode(f, &p, &(mesg->addr)); |
114 | |
|
115 | 0 | if (H5_IS_BUFFER_OVERFLOW(p, H5F_sizeof_size(f), p_end)) |
116 | 0 | HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "ran off end of input buffer while decoding"); |
117 | 0 | H5F_DECODE_LENGTH(f, p, mesg->size); |
118 | | |
119 | | /* Set return value */ |
120 | 0 | ret_value = (void *)mesg; |
121 | |
|
122 | 0 | done: |
123 | 0 | if (!ret_value && mesg) |
124 | 0 | H5FL_FREE(H5O_mdci_t, mesg); |
125 | |
|
126 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
127 | 0 | } /* end H5O__mdci_decode() */ |
128 | | |
129 | | /*------------------------------------------------------------------------- |
130 | | * Function: H5O__mdci_encode |
131 | | * |
132 | | * Purpose: Encode metadata cache image message |
133 | | * |
134 | | * Return: Non-negative on success/Negative on failure |
135 | | * |
136 | | *------------------------------------------------------------------------- |
137 | | */ |
138 | | static herr_t |
139 | | H5O__mdci_encode(H5F_t *f, bool H5_ATTR_UNUSED disable_shared, size_t H5_ATTR_UNUSED p_size, uint8_t *p, |
140 | | const void *_mesg) |
141 | 0 | { |
142 | 0 | const H5O_mdci_t *mesg = (const H5O_mdci_t *)_mesg; |
143 | |
|
144 | 0 | FUNC_ENTER_PACKAGE_NOERR |
145 | | |
146 | | /* Sanity check */ |
147 | 0 | assert(f); |
148 | 0 | assert(p); |
149 | 0 | assert(mesg); |
150 | | |
151 | | /* encode */ |
152 | 0 | *p++ = H5O_MDCI_VERSION_0; |
153 | 0 | H5F_addr_encode(f, &p, mesg->addr); |
154 | 0 | H5F_ENCODE_LENGTH(f, p, mesg->size); |
155 | | |
156 | 0 | FUNC_LEAVE_NOAPI(SUCCEED) |
157 | 0 | } /* end H5O__mdci_encode() */ |
158 | | |
159 | | /*------------------------------------------------------------------------- |
160 | | * Function: H5O__mdci_copy |
161 | | * |
162 | | * Purpose: Copies a message from _MESG to _DEST, allocating _DEST if |
163 | | * necessary. |
164 | | * |
165 | | * Return: Success: Ptr to _DEST |
166 | | * Failure: NULL |
167 | | * |
168 | | *------------------------------------------------------------------------- |
169 | | */ |
170 | | static void * |
171 | | H5O__mdci_copy(const void *_mesg, void *_dest) |
172 | 0 | { |
173 | 0 | const H5O_mdci_t *mesg = (const H5O_mdci_t *)_mesg; |
174 | 0 | H5O_mdci_t *dest = (H5O_mdci_t *)_dest; |
175 | 0 | void *ret_value = NULL; /* Return value */ |
176 | |
|
177 | 0 | FUNC_ENTER_PACKAGE |
178 | | |
179 | | /* check args */ |
180 | 0 | assert(mesg); |
181 | 0 | if (!dest && NULL == (dest = H5FL_MALLOC(H5O_mdci_t))) |
182 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); |
183 | | |
184 | | /* copy */ |
185 | 0 | *dest = *mesg; |
186 | | |
187 | | /* Set return value */ |
188 | 0 | ret_value = dest; |
189 | |
|
190 | 0 | done: |
191 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
192 | 0 | } /* end H5O_mdci__copy() */ |
193 | | |
194 | | /*------------------------------------------------------------------------- |
195 | | * Function: H5O__mdci_size |
196 | | * |
197 | | * Purpose: Returns the size of the raw message in bytes not counting |
198 | | * the message type or size fields, but only the data fields. |
199 | | * This function doesn't take into account alignment. |
200 | | * |
201 | | * Return: Success: Message data size in bytes without alignment. |
202 | | * |
203 | | * Failure: zero |
204 | | * |
205 | | *------------------------------------------------------------------------- |
206 | | */ |
207 | | static size_t |
208 | | H5O__mdci_size(const H5F_t *f, bool H5_ATTR_UNUSED disable_shared, const void H5_ATTR_UNUSED *_mesg) |
209 | 0 | { |
210 | 0 | size_t ret_value = 0; /* Return value */ |
211 | |
|
212 | 0 | FUNC_ENTER_PACKAGE_NOERR |
213 | | |
214 | | /* Set return value */ |
215 | 0 | ret_value = (size_t)(1 + /* Version number */ |
216 | 0 | H5F_SIZEOF_ADDR(f) + /* addr of metadata cache */ |
217 | | /* image block */ |
218 | 0 | H5F_SIZEOF_SIZE(f)); /* length of metadata cache */ |
219 | | /* image block */ |
220 | |
|
221 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
222 | 0 | } /* end H5O__mdci_size() */ |
223 | | |
224 | | /*------------------------------------------------------------------------- |
225 | | * Function: H5O__mdci_free |
226 | | * |
227 | | * Purpose: Free the message |
228 | | * |
229 | | * Return: Non-negative on success/Negative on failure |
230 | | * |
231 | | *------------------------------------------------------------------------- |
232 | | */ |
233 | | static herr_t |
234 | | H5O__mdci_free(void *mesg) |
235 | 0 | { |
236 | 0 | FUNC_ENTER_PACKAGE_NOERR |
237 | |
|
238 | 0 | assert(mesg); |
239 | |
|
240 | 0 | mesg = H5FL_FREE(H5O_mdci_t, mesg); |
241 | |
|
242 | 0 | FUNC_LEAVE_NOAPI(SUCCEED) |
243 | 0 | } /* end H5O__mdci_free() */ |
244 | | |
245 | | /*------------------------------------------------------------------------- |
246 | | * Function: H5O__mdci_delete |
247 | | * |
248 | | * Purpose: Free file space referenced by message |
249 | | * |
250 | | * Return: Non-negative on success/Negative on failure |
251 | | * |
252 | | *------------------------------------------------------------------------- |
253 | | */ |
254 | | static herr_t |
255 | | H5O__mdci_delete(H5F_t *f, H5O_t H5_ATTR_UNUSED *open_oh, void *_mesg) |
256 | 0 | { |
257 | 0 | H5O_mdci_t *mesg = (H5O_mdci_t *)_mesg; |
258 | 0 | haddr_t final_eoa; /* For sanity check */ |
259 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
260 | |
|
261 | 0 | FUNC_ENTER_PACKAGE |
262 | | |
263 | | /* check args */ |
264 | 0 | assert(f); |
265 | 0 | assert(mesg); |
266 | | |
267 | | /* Free file space for cache image */ |
268 | 0 | if (H5_addr_defined(mesg->addr)) { |
269 | | /* The space for the cache image block was allocated directly |
270 | | * from the VFD layer at the end of file. As this was the |
271 | | * last file space allocation before shutdown, the cache image |
272 | | * should still be the last item in the file. |
273 | | */ |
274 | 0 | if (f->shared->closing) { |
275 | | /* Get the eoa, and verify that it has the expected value */ |
276 | 0 | if (HADDR_UNDEF == (final_eoa = H5FD_get_eoa(f->shared->lf, H5FD_MEM_DEFAULT))) |
277 | 0 | HGOTO_ERROR(H5E_CACHE, H5E_CANTGET, FAIL, "unable to get file size"); |
278 | | |
279 | 0 | assert(H5_addr_eq(final_eoa, mesg->addr + mesg->size)); |
280 | |
|
281 | 0 | if (H5FD_free(f->shared->lf, H5FD_MEM_SUPER, f, mesg->addr, mesg->size) < 0) |
282 | 0 | HGOTO_ERROR(H5E_CACHE, H5E_CANTFREE, FAIL, "can't free MDC image"); |
283 | 0 | } |
284 | 0 | else if (H5MF_xfree(f, H5FD_MEM_SUPER, mesg->addr, mesg->size) < 0) |
285 | 0 | HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to free file space for cache image block"); |
286 | 0 | } /* end if */ |
287 | | |
288 | 0 | done: |
289 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
290 | 0 | } /* end H5O__mdci_delete() */ |
291 | | |
292 | | /*------------------------------------------------------------------------- |
293 | | * Function: H5O__mdci_debug |
294 | | * |
295 | | * Purpose: Prints debugging info. |
296 | | * |
297 | | * Return: Non-negative on success/Negative on failure |
298 | | * |
299 | | *------------------------------------------------------------------------- |
300 | | */ |
301 | | static herr_t |
302 | | H5O__mdci_debug(H5F_t H5_ATTR_UNUSED *f, const void *_mesg, FILE *stream, int indent, int fwidth) |
303 | 0 | { |
304 | 0 | const H5O_mdci_t *mdci = (const H5O_mdci_t *)_mesg; |
305 | |
|
306 | 0 | FUNC_ENTER_PACKAGE_NOERR |
307 | | |
308 | | /* check args */ |
309 | 0 | assert(f); |
310 | 0 | assert(mdci); |
311 | 0 | assert(stream); |
312 | 0 | assert(indent >= 0); |
313 | 0 | assert(fwidth >= 0); |
314 | |
|
315 | 0 | fprintf(stream, "%*s%-*s %" PRIuHADDR "\n", indent, "", fwidth, |
316 | 0 | "Metadata Cache Image Block address:", mdci->addr); |
317 | |
|
318 | 0 | fprintf(stream, "%*s%-*s %" PRIuHSIZE "\n", indent, "", fwidth, |
319 | 0 | "Metadata Cache Image Block size in bytes:", mdci->size); |
320 | |
|
321 | 0 | FUNC_LEAVE_NOAPI(SUCCEED) |
322 | 0 | } /* end H5O__mdci_debug() */ |