/src/hdf5/src/H5Ocache_image.c
Line | Count | Source |
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 | 47 | #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 | 47 | { |
91 | 47 | H5O_mdci_t *mesg = NULL; /* New cache image message */ |
92 | 47 | const uint8_t *p_end = p + p_size - 1; /* End of the p buffer */ |
93 | 47 | void *ret_value = NULL; |
94 | | |
95 | 47 | FUNC_ENTER_PACKAGE |
96 | | |
97 | 47 | assert(f); |
98 | 47 | assert(p); |
99 | | |
100 | | /* Version of message */ |
101 | 47 | 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 | 47 | if (*p++ != H5O_MDCI_VERSION_0) |
104 | 1 | HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "bad version number for message"); |
105 | | |
106 | | /* Allocate space for message */ |
107 | 46 | if (NULL == (mesg = (H5O_mdci_t *)H5FL_MALLOC(H5O_mdci_t))) |
108 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, |
109 | 46 | "memory allocation failed for metadata cache image message"); |
110 | | |
111 | 46 | 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 | 46 | H5F_addr_decode(f, &p, &(mesg->addr)); |
114 | | |
115 | 46 | 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 | 46 | H5F_DECODE_LENGTH(f, p, mesg->size); |
118 | | |
119 | 46 | if (H5_addr_defined(mesg->addr) && mesg->size) { |
120 | 36 | if (mesg->addr >= (HADDR_UNDEF - mesg->size)) |
121 | 4 | HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "address plus size overflows"); |
122 | 32 | if ((mesg->addr + mesg->size) > H5F_get_eoa(f, H5FD_MEM_SUPER)) |
123 | 29 | HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "address plus size exceeds file eoa"); |
124 | 32 | } |
125 | | |
126 | | /* Set return value */ |
127 | 13 | ret_value = (void *)mesg; |
128 | | |
129 | 47 | done: |
130 | 47 | if (!ret_value && mesg) |
131 | 33 | H5FL_FREE(H5O_mdci_t, mesg); |
132 | | |
133 | 47 | FUNC_LEAVE_NOAPI(ret_value) |
134 | 47 | } /* end H5O__mdci_decode() */ |
135 | | |
136 | | /*------------------------------------------------------------------------- |
137 | | * Function: H5O__mdci_encode |
138 | | * |
139 | | * Purpose: Encode metadata cache image message |
140 | | * |
141 | | * Return: Non-negative on success/Negative on failure |
142 | | * |
143 | | *------------------------------------------------------------------------- |
144 | | */ |
145 | | static herr_t |
146 | | H5O__mdci_encode(H5F_t *f, bool H5_ATTR_UNUSED disable_shared, size_t H5_ATTR_UNUSED p_size, uint8_t *p, |
147 | | const void *_mesg) |
148 | 0 | { |
149 | 0 | const H5O_mdci_t *mesg = (const H5O_mdci_t *)_mesg; |
150 | |
|
151 | 0 | FUNC_ENTER_PACKAGE_NOERR |
152 | | |
153 | | /* Sanity check */ |
154 | 0 | assert(f); |
155 | 0 | assert(p); |
156 | 0 | assert(mesg); |
157 | | |
158 | | /* encode */ |
159 | 0 | *p++ = H5O_MDCI_VERSION_0; |
160 | 0 | H5F_addr_encode(f, &p, mesg->addr); |
161 | 0 | H5F_ENCODE_LENGTH(f, p, mesg->size); |
162 | | |
163 | 0 | FUNC_LEAVE_NOAPI(SUCCEED) |
164 | 0 | } /* end H5O__mdci_encode() */ |
165 | | |
166 | | /*------------------------------------------------------------------------- |
167 | | * Function: H5O__mdci_copy |
168 | | * |
169 | | * Purpose: Copies a message from _MESG to _DEST, allocating _DEST if |
170 | | * necessary. |
171 | | * |
172 | | * Return: Success: Ptr to _DEST |
173 | | * Failure: NULL |
174 | | * |
175 | | *------------------------------------------------------------------------- |
176 | | */ |
177 | | static void * |
178 | | H5O__mdci_copy(const void *_mesg, void *_dest) |
179 | 13 | { |
180 | 13 | const H5O_mdci_t *mesg = (const H5O_mdci_t *)_mesg; |
181 | 13 | H5O_mdci_t *dest = (H5O_mdci_t *)_dest; |
182 | 13 | void *ret_value = NULL; /* Return value */ |
183 | | |
184 | 13 | FUNC_ENTER_PACKAGE |
185 | | |
186 | | /* check args */ |
187 | 13 | assert(mesg); |
188 | 13 | if (!dest && NULL == (dest = H5FL_MALLOC(H5O_mdci_t))) |
189 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); |
190 | | |
191 | | /* copy */ |
192 | 13 | *dest = *mesg; |
193 | | |
194 | | /* Set return value */ |
195 | 13 | ret_value = dest; |
196 | | |
197 | 13 | done: |
198 | 13 | FUNC_LEAVE_NOAPI(ret_value) |
199 | 13 | } /* end H5O_mdci__copy() */ |
200 | | |
201 | | /*------------------------------------------------------------------------- |
202 | | * Function: H5O__mdci_size |
203 | | * |
204 | | * Purpose: Returns the size of the raw message in bytes not counting |
205 | | * the message type or size fields, but only the data fields. |
206 | | * This function doesn't take into account alignment. |
207 | | * |
208 | | * Return: Success: Message data size in bytes without alignment. |
209 | | * |
210 | | * Failure: zero |
211 | | * |
212 | | *------------------------------------------------------------------------- |
213 | | */ |
214 | | static size_t |
215 | | H5O__mdci_size(const H5F_t *f, bool H5_ATTR_UNUSED disable_shared, const void H5_ATTR_UNUSED *_mesg) |
216 | 0 | { |
217 | 0 | size_t ret_value = 0; /* Return value */ |
218 | |
|
219 | 0 | FUNC_ENTER_PACKAGE_NOERR |
220 | | |
221 | | /* Set return value */ |
222 | 0 | ret_value = (size_t)(1 + /* Version number */ |
223 | 0 | H5F_SIZEOF_ADDR(f) + /* addr of metadata cache */ |
224 | | /* image block */ |
225 | 0 | H5F_SIZEOF_SIZE(f)); /* length of metadata cache */ |
226 | | /* image block */ |
227 | |
|
228 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
229 | 0 | } /* end H5O__mdci_size() */ |
230 | | |
231 | | /*------------------------------------------------------------------------- |
232 | | * Function: H5O__mdci_free |
233 | | * |
234 | | * Purpose: Free the message |
235 | | * |
236 | | * Return: Non-negative on success/Negative on failure |
237 | | * |
238 | | *------------------------------------------------------------------------- |
239 | | */ |
240 | | static herr_t |
241 | | H5O__mdci_free(void *mesg) |
242 | 13 | { |
243 | 13 | FUNC_ENTER_PACKAGE_NOERR |
244 | | |
245 | 13 | assert(mesg); |
246 | | |
247 | 13 | mesg = H5FL_FREE(H5O_mdci_t, mesg); |
248 | | |
249 | 13 | FUNC_LEAVE_NOAPI(SUCCEED) |
250 | 13 | } /* end H5O__mdci_free() */ |
251 | | |
252 | | /*------------------------------------------------------------------------- |
253 | | * Function: H5O__mdci_delete |
254 | | * |
255 | | * Purpose: Free file space referenced by message |
256 | | * |
257 | | * Return: Non-negative on success/Negative on failure |
258 | | * |
259 | | *------------------------------------------------------------------------- |
260 | | */ |
261 | | static herr_t |
262 | | H5O__mdci_delete(H5F_t *f, H5O_t H5_ATTR_UNUSED *open_oh, void *_mesg) |
263 | 0 | { |
264 | 0 | H5O_mdci_t *mesg = (H5O_mdci_t *)_mesg; |
265 | 0 | haddr_t final_eoa; /* For sanity check */ |
266 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
267 | |
|
268 | 0 | FUNC_ENTER_PACKAGE |
269 | | |
270 | | /* check args */ |
271 | 0 | assert(f); |
272 | 0 | assert(mesg); |
273 | | |
274 | | /* Free file space for cache image */ |
275 | 0 | if (H5_addr_defined(mesg->addr)) { |
276 | | /* The space for the cache image block was allocated directly |
277 | | * from the VFD layer at the end of file. As this was the |
278 | | * last file space allocation before shutdown, the cache image |
279 | | * should still be the last item in the file. |
280 | | */ |
281 | 0 | if (f->shared->closing) { |
282 | | /* Get the eoa, and verify that it has the expected value */ |
283 | 0 | if (HADDR_UNDEF == (final_eoa = H5FD_get_eoa(f->shared->lf, H5FD_MEM_DEFAULT))) |
284 | 0 | HGOTO_ERROR(H5E_CACHE, H5E_CANTGET, FAIL, "unable to get file size"); |
285 | | |
286 | 0 | assert(H5_addr_eq(final_eoa, mesg->addr + mesg->size)); |
287 | |
|
288 | 0 | if (H5FD_free(f->shared->lf, H5FD_MEM_SUPER, f, mesg->addr, mesg->size) < 0) |
289 | 0 | HGOTO_ERROR(H5E_CACHE, H5E_CANTFREE, FAIL, "can't free MDC image"); |
290 | 0 | } |
291 | 0 | else if (H5MF_xfree(f, H5FD_MEM_SUPER, mesg->addr, mesg->size) < 0) |
292 | 0 | HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to free file space for cache image block"); |
293 | 0 | } /* end if */ |
294 | | |
295 | 0 | done: |
296 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
297 | 0 | } /* end H5O__mdci_delete() */ |
298 | | |
299 | | /*------------------------------------------------------------------------- |
300 | | * Function: H5O__mdci_debug |
301 | | * |
302 | | * Purpose: Prints debugging info. |
303 | | * |
304 | | * Return: Non-negative on success/Negative on failure |
305 | | * |
306 | | *------------------------------------------------------------------------- |
307 | | */ |
308 | | static herr_t |
309 | | H5O__mdci_debug(H5F_t H5_ATTR_UNUSED *f, const void *_mesg, FILE *stream, int indent, int fwidth) |
310 | 0 | { |
311 | 0 | const H5O_mdci_t *mdci = (const H5O_mdci_t *)_mesg; |
312 | |
|
313 | 0 | FUNC_ENTER_PACKAGE_NOERR |
314 | | |
315 | | /* check args */ |
316 | 0 | assert(f); |
317 | 0 | assert(mdci); |
318 | 0 | assert(stream); |
319 | 0 | assert(indent >= 0); |
320 | 0 | assert(fwidth >= 0); |
321 | |
|
322 | 0 | fprintf(stream, "%*s%-*s %" PRIuHADDR "\n", indent, "", fwidth, |
323 | 0 | "Metadata Cache Image Block address:", mdci->addr); |
324 | |
|
325 | 0 | fprintf(stream, "%*s%-*s %" PRIuHSIZE "\n", indent, "", fwidth, |
326 | 0 | "Metadata Cache Image Block size in bytes:", mdci->size); |
327 | |
|
328 | 0 | FUNC_LEAVE_NOAPI(SUCCEED) |
329 | 0 | } /* end H5O__mdci_debug() */ |