/src/hdf5/src/H5FDmulti.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 | | * Purpose: Implements a file driver which dispatches I/O requests to |
15 | | * other file drivers depending on the purpose of the address |
16 | | * region being accessed. For instance, all meta-data could be |
17 | | * place in one file while all raw data goes to some other file. |
18 | | * This also serves as an example of coding a complex file driver, |
19 | | * therefore, it should not use any non-public definitions. |
20 | | */ |
21 | | #include <assert.h> |
22 | | #include <stdlib.h> |
23 | | #include <string.h> |
24 | | |
25 | | #include "hdf5.h" |
26 | | |
27 | | #include "H5warnings.h" |
28 | | |
29 | | #ifndef false |
30 | | #define false 0 |
31 | | #endif |
32 | | #ifndef true |
33 | | #define true 1 |
34 | | #endif |
35 | | |
36 | | /* Windows doesn't like some POSIX names and redefines them with an |
37 | | * underscore |
38 | | */ |
39 | | #ifdef _WIN32 |
40 | | #define my_strdup _strdup |
41 | | #else |
42 | 0 | #define my_strdup strdup |
43 | | #endif |
44 | | |
45 | | /* Loop through all mapped files */ |
46 | | #define UNIQUE_MEMBERS_CORE(MAP, ITER, SEEN, LOOPVAR) \ |
47 | 0 | { \ |
48 | 0 | H5FD_mem_t ITER, LOOPVAR; \ |
49 | 0 | unsigned SEEN[H5FD_MEM_NTYPES]; \ |
50 | 0 | \ |
51 | 0 | memset(SEEN, 0, sizeof SEEN); \ |
52 | 0 | for (ITER = H5FD_MEM_SUPER; ITER < H5FD_MEM_NTYPES; ITER = (H5FD_mem_t)(ITER + 1)) { \ |
53 | 0 | LOOPVAR = MAP[ITER]; \ |
54 | 0 | if (H5FD_MEM_DEFAULT == LOOPVAR) \ |
55 | 0 | LOOPVAR = ITER; \ |
56 | 0 | assert(LOOPVAR > 0 && LOOPVAR < H5FD_MEM_NTYPES); \ |
57 | 0 | if (SEEN[LOOPVAR]++) \ |
58 | 0 | continue; |
59 | | |
60 | | /* Need two front-ends, since they are nested sometimes */ |
61 | 0 | #define UNIQUE_MEMBERS(MAP, LOOPVAR) UNIQUE_MEMBERS_CORE(MAP, _unmapped, _seen, LOOPVAR) |
62 | 0 | #define UNIQUE_MEMBERS2(MAP, LOOPVAR) UNIQUE_MEMBERS_CORE(MAP, _unmapped2, _seen2, LOOPVAR) |
63 | | |
64 | | #define ALL_MEMBERS(LOOPVAR) \ |
65 | 0 | { \ |
66 | 0 | H5FD_mem_t LOOPVAR; \ |
67 | 0 | for (LOOPVAR = H5FD_MEM_DEFAULT; LOOPVAR < H5FD_MEM_NTYPES; LOOPVAR = (H5FD_mem_t)(LOOPVAR + 1)) { |
68 | | |
69 | | #define END_MEMBERS \ |
70 | 0 | } \ |
71 | 0 | } |
72 | | |
73 | | #define H5FD_MULT_MAX_FILE_NAME_LEN 1024 |
74 | | |
75 | | /* Driver-specific file access properties */ |
76 | | typedef struct H5FD_multi_fapl_t { |
77 | | H5FD_mem_t memb_map[H5FD_MEM_NTYPES]; /*memory usage map */ |
78 | | hid_t memb_fapl[H5FD_MEM_NTYPES]; /*member access properties */ |
79 | | char *memb_name[H5FD_MEM_NTYPES]; /*name generators */ |
80 | | haddr_t memb_addr[H5FD_MEM_NTYPES]; /*starting addr per member */ |
81 | | bool relax; /*less stringent error checking */ |
82 | | } H5FD_multi_fapl_t; |
83 | | |
84 | | /* |
85 | | * The description of a file belonging to this driver. The file access |
86 | | * properties and member names do not have to be copied into this struct |
87 | | * since they will be held open by the file access property list which is |
88 | | * copied into the parent file struct in H5F_open(). |
89 | | */ |
90 | | typedef struct H5FD_multi_t { |
91 | | H5FD_t pub; /*public stuff, must be first */ |
92 | | H5FD_multi_fapl_t fa; /*driver-specific file access properties */ |
93 | | haddr_t memb_next[H5FD_MEM_NTYPES]; /*addr of next member */ |
94 | | H5FD_t *memb[H5FD_MEM_NTYPES]; /*member pointers */ |
95 | | haddr_t memb_eoa[H5FD_MEM_NTYPES]; /*EOA for individual files, |
96 | | *end of allocated addresses. v1.6 library |
97 | | *have the EOA for the entire file. But it's |
98 | | *meaningless for MULTI file. We replaced it |
99 | | *with the EOAs for individual files */ |
100 | | unsigned flags; /*file open flags saved for debugging */ |
101 | | char *name; /*name passed to H5Fopen or H5Fcreate */ |
102 | | } H5FD_multi_t; |
103 | | |
104 | | /* Driver specific data transfer properties */ |
105 | | typedef struct H5FD_multi_dxpl_t { |
106 | | hid_t memb_dxpl[H5FD_MEM_NTYPES]; /*member data xfer properties*/ |
107 | | } H5FD_multi_dxpl_t; |
108 | | |
109 | | /* Private functions */ |
110 | | static herr_t H5FD_split_populate_config(const char *meta_ext, hid_t meta_plist_id, const char *raw_ext, |
111 | | hid_t raw_plist_id, bool relax, H5FD_multi_fapl_t *fa_out); |
112 | | static herr_t H5FD_multi_populate_config(const H5FD_mem_t *memb_map, const hid_t *memb_fapl, |
113 | | const char *const *memb_name, const haddr_t *memb_addr, bool relax, |
114 | | H5FD_multi_fapl_t *fa_out); |
115 | | static int compute_next(H5FD_multi_t *file); |
116 | | static int open_members(H5FD_multi_t *file); |
117 | | |
118 | | /* Callback prototypes */ |
119 | | static hsize_t H5FD_multi_sb_size(H5FD_t *file); |
120 | | static herr_t H5FD_multi_sb_encode(H5FD_t *file, char *name /*out*/, unsigned char *buf /*out*/); |
121 | | static herr_t H5FD_multi_sb_decode(H5FD_t *file, const char *name, const unsigned char *buf); |
122 | | static void *H5FD_multi_fapl_get(H5FD_t *file); |
123 | | static void *H5FD_multi_fapl_copy(const void *_old_fa); |
124 | | static herr_t H5FD_multi_fapl_free(void *_fa); |
125 | | static H5FD_t *H5FD_multi_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr); |
126 | | static herr_t H5FD_multi_close(H5FD_t *_file); |
127 | | static int H5FD_multi_cmp(const H5FD_t *_f1, const H5FD_t *_f2); |
128 | | static herr_t H5FD_multi_query(const H5FD_t *_f1, unsigned long *flags); |
129 | | static herr_t H5FD_multi_get_type_map(const H5FD_t *file, H5FD_mem_t *type_map); |
130 | | static haddr_t H5FD_multi_get_eoa(const H5FD_t *_file, H5FD_mem_t type); |
131 | | static herr_t H5FD_multi_set_eoa(H5FD_t *_file, H5FD_mem_t type, haddr_t eoa); |
132 | | static haddr_t H5FD_multi_get_eof(const H5FD_t *_file, H5FD_mem_t type); |
133 | | static herr_t H5FD_multi_get_handle(H5FD_t *_file, hid_t fapl, void **file_handle); |
134 | | static haddr_t H5FD_multi_alloc(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, hsize_t size); |
135 | | static herr_t H5FD_multi_free(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, hsize_t size); |
136 | | static herr_t H5FD_multi_read(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, size_t size, |
137 | | void *_buf /*out*/); |
138 | | static herr_t H5FD_multi_write(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, size_t size, |
139 | | const void *_buf); |
140 | | static herr_t H5FD_multi_flush(H5FD_t *_file, hid_t dxpl_id, bool closing); |
141 | | static herr_t H5FD_multi_truncate(H5FD_t *_file, hid_t dxpl_id, bool closing); |
142 | | static herr_t H5FD_multi_lock(H5FD_t *_file, bool rw); |
143 | | static herr_t H5FD_multi_unlock(H5FD_t *_file); |
144 | | static herr_t H5FD_multi_delete(const char *filename, hid_t fapl_id); |
145 | | static herr_t H5FD_multi_ctl(H5FD_t *_file, uint64_t op_code, uint64_t flags, const void *input, |
146 | | void **output); |
147 | | |
148 | | /* The class struct */ |
149 | | const H5FD_class_t H5FD_multi_g = { |
150 | | H5FD_CLASS_VERSION, /* struct version */ |
151 | | H5_VFD_MULTI, /* value */ |
152 | | "multi", /* name */ |
153 | | HADDR_MAX, /* maxaddr */ |
154 | | H5F_CLOSE_WEAK, /* fc_degree */ |
155 | | NULL, /* terminate */ |
156 | | H5FD_multi_sb_size, /* sb_size */ |
157 | | H5FD_multi_sb_encode, /* sb_encode */ |
158 | | H5FD_multi_sb_decode, /* sb_decode */ |
159 | | sizeof(H5FD_multi_fapl_t), /* fapl_size */ |
160 | | H5FD_multi_fapl_get, /* fapl_get */ |
161 | | H5FD_multi_fapl_copy, /* fapl_copy */ |
162 | | H5FD_multi_fapl_free, /* fapl_free */ |
163 | | 0, /* dxpl_size */ |
164 | | NULL, /* dxpl_copy */ |
165 | | NULL, /* dxpl_free */ |
166 | | H5FD_multi_open, /* open */ |
167 | | H5FD_multi_close, /* close */ |
168 | | H5FD_multi_cmp, /* cmp */ |
169 | | H5FD_multi_query, /* query */ |
170 | | H5FD_multi_get_type_map, /* get_type_map */ |
171 | | H5FD_multi_alloc, /* alloc */ |
172 | | H5FD_multi_free, /* free */ |
173 | | H5FD_multi_get_eoa, /* get_eoa */ |
174 | | H5FD_multi_set_eoa, /* set_eoa */ |
175 | | H5FD_multi_get_eof, /* get_eof */ |
176 | | H5FD_multi_get_handle, /* get_handle */ |
177 | | H5FD_multi_read, /* read */ |
178 | | H5FD_multi_write, /* write */ |
179 | | NULL, /*read_vector */ |
180 | | NULL, /*write_vector */ |
181 | | NULL, /* read_selection */ |
182 | | NULL, /* write_selection */ |
183 | | H5FD_multi_flush, /* flush */ |
184 | | H5FD_multi_truncate, /* truncate */ |
185 | | H5FD_multi_lock, /* lock */ |
186 | | H5FD_multi_unlock, /* unlock */ |
187 | | H5FD_multi_delete, /* del */ |
188 | | H5FD_multi_ctl, /* ctl */ |
189 | | H5FD_FLMAP_DEFAULT /* fl_map */ |
190 | | }; |
191 | | |
192 | | /*------------------------------------------------------------------------- |
193 | | * Function: H5Pset_fapl_split |
194 | | * |
195 | | * Purpose: Compatibility function. Makes the multi driver act like the |
196 | | * old split driver which stored meta data in one file and raw |
197 | | * data in another file. |
198 | | * |
199 | | * Return: Success: 0 |
200 | | * |
201 | | * Failure: -1 |
202 | | * |
203 | | *------------------------------------------------------------------------- |
204 | | */ |
205 | | herr_t |
206 | | H5Pset_fapl_split(hid_t fapl, const char *meta_ext, hid_t meta_plist_id, const char *raw_ext, |
207 | | hid_t raw_plist_id) |
208 | 0 | { |
209 | 0 | H5FD_multi_fapl_t fa; |
210 | | |
211 | | /* Clear the error stack */ |
212 | 0 | H5Eclear2(H5E_DEFAULT); |
213 | |
|
214 | 0 | if (H5FD_split_populate_config(meta_ext, meta_plist_id, raw_ext, raw_plist_id, true, &fa) < 0) |
215 | 0 | H5Epush_ret(__func__, H5E_ERR_CLS, H5E_INTERNAL, H5E_CANTSET, |
216 | 0 | "can't setup split driver configuration", -1); |
217 | | |
218 | 0 | return H5Pset_driver(fapl, H5FD_MULTI, &fa); |
219 | 0 | } |
220 | | |
221 | | /*------------------------------------------------------------------------- |
222 | | * Function: H5Pset_fapl_multi |
223 | | * |
224 | | * Purpose: Sets the file access property list FAPL_ID to use the multi |
225 | | * driver. The MEMB_MAP array maps memory usage types to other |
226 | | * memory usage types and is the mechanism which allows the |
227 | | * caller to specify how many files are created. The array |
228 | | * contains H5FD_MEM_NTYPES entries which are either the value |
229 | | * H5FD_MEM_DEFAULT or a memory usage type and the number of |
230 | | * unique values determines the number of files which are |
231 | | * opened. For each memory usage type which will be associated |
232 | | * with a file the MEMB_FAPL array should have a property list |
233 | | * and the MEMB_NAME array should be a name generator (a |
234 | | * printf-style format with a %s which will be replaced with the |
235 | | * name passed to H5FDopen(), usually from H5Fcreate() or |
236 | | * H5Fopen()). |
237 | | * |
238 | | * If RELAX is set then opening an existing file for read-only |
239 | | * access will not fail if some file members are missing. This |
240 | | * allows a file to be accessed in a limited sense if just the |
241 | | * meta data is available. |
242 | | * |
243 | | * Defaults: Default values for each of the optional arguments are: |
244 | | * |
245 | | * memb_map: The default member map has the value |
246 | | * H5FD_MEM_DEFAULT for each element. |
247 | | * |
248 | | * memb_fapl: The value H5P_DEFAULT for each element. |
249 | | * |
250 | | * memb_name: The string `%s-X.h5' where `X' is one of the |
251 | | * letters `s' (H5FD_MEM_SUPER), |
252 | | * `b' (H5FD_MEM_BTREE), `r' (H5FD_MEM_DRAW), |
253 | | * `g' (H5FD_MEM_GHEAP), 'l' (H5FD_MEM_LHEAP), |
254 | | * `o' (H5FD_MEM_OHDR). |
255 | | * |
256 | | * memb_addr: The value HADDR_UNDEF for each element. |
257 | | * |
258 | | * |
259 | | * Example: To set up a multi file access property list which partitions |
260 | | * data into meta and raw files each being 1/2 of the address |
261 | | * space one would say: |
262 | | * |
263 | | * H5FD_mem_t mt, memb_map[H5FD_MEM_NTYPES]; |
264 | | * hid_t memb_fapl[H5FD_MEM_NTYPES]; |
265 | | * const char *memb[H5FD_MEM_NTYPES]; |
266 | | * haddr_t memb_addr[H5FD_MEM_NTYPES]; |
267 | | * |
268 | | * // The mapping... |
269 | | * for (mt=0; mt<H5FD_MEM_NTYPES; mt++) { |
270 | | * memb_map[mt] = H5FD_MEM_SUPER; |
271 | | * } |
272 | | * memb_map[H5FD_MEM_DRAW] = H5FD_MEM_DRAW; |
273 | | * |
274 | | * // Member information |
275 | | * memb_fapl[H5FD_MEM_SUPER] = H5P_DEFAULT; |
276 | | * memb_name[H5FD_MEM_SUPER] = "%s.meta"; |
277 | | * memb_addr[H5FD_MEM_SUPER] = 0; |
278 | | * |
279 | | * memb_fapl[H5FD_MEM_DRAW] = H5P_DEFAULT; |
280 | | * memb_name[H5FD_MEM_DRAW] = "%s.raw"; |
281 | | * memb_addr[H5FD_MEM_DRAW] = HADDR_MAX/2; |
282 | | * |
283 | | * hid_t fapl = H5Pcreate(H5P_FILE_ACCESS); |
284 | | * H5Pset_fapl_multi(fapl, memb_map, memb_fapl, |
285 | | * memb_name, memb_addr, true); |
286 | | * |
287 | | * |
288 | | * Return: Success: Non-negative |
289 | | * |
290 | | * Failure: Negative |
291 | | * |
292 | | *------------------------------------------------------------------------- |
293 | | */ |
294 | | herr_t |
295 | | H5Pset_fapl_multi(hid_t fapl_id, const H5FD_mem_t *memb_map, const hid_t *memb_fapl, |
296 | | const char *const *memb_name, const haddr_t *memb_addr, hbool_t relax) |
297 | 0 | { |
298 | 0 | H5FD_multi_fapl_t fa; |
299 | | |
300 | | /* Clear the error stack */ |
301 | 0 | H5Eclear2(H5E_DEFAULT); |
302 | | |
303 | | /* Check arguments and supply default values */ |
304 | 0 | if (H5I_GENPROP_LST != H5Iget_type(fapl_id) || true != H5Pisa_class(fapl_id, H5P_FILE_ACCESS)) |
305 | 0 | H5Epush_ret(__func__, H5E_ERR_CLS, H5E_PLIST, H5E_BADVALUE, "not an access list", -1); |
306 | 0 | if (H5FD_multi_populate_config(memb_map, memb_fapl, memb_name, memb_addr, relax, &fa) < 0) |
307 | 0 | H5Epush_ret(__func__, H5E_ERR_CLS, H5E_INTERNAL, H5E_CANTSET, "can't setup driver configuration", -1); |
308 | | |
309 | 0 | return H5Pset_driver(fapl_id, H5FD_MULTI, &fa); |
310 | 0 | } |
311 | | |
312 | | /*------------------------------------------------------------------------- |
313 | | * Function: H5Pget_fapl_multi |
314 | | * |
315 | | * Purpose: Returns information about the multi file access property |
316 | | * list though the function arguments which are the same as for |
317 | | * H5Pset_fapl_multi() above. |
318 | | * |
319 | | * Return: Success: Non-negative |
320 | | * |
321 | | * Failure: Negative |
322 | | * |
323 | | *------------------------------------------------------------------------- |
324 | | */ |
325 | | herr_t |
326 | | H5Pget_fapl_multi(hid_t fapl_id, H5FD_mem_t *memb_map /*out*/, hid_t *memb_fapl /*out*/, |
327 | | char **memb_name /*out*/, haddr_t *memb_addr /*out*/, hbool_t *relax) |
328 | 0 | { |
329 | 0 | const H5FD_multi_fapl_t *fa; |
330 | 0 | H5FD_multi_fapl_t default_fa; |
331 | 0 | H5FD_mem_t mt; |
332 | | |
333 | | /* Clear the error stack */ |
334 | 0 | H5Eclear2(H5E_DEFAULT); |
335 | |
|
336 | 0 | if (H5I_GENPROP_LST != H5Iget_type(fapl_id) || true != H5Pisa_class(fapl_id, H5P_FILE_ACCESS)) |
337 | 0 | H5Epush_ret(__func__, H5E_ERR_CLS, H5E_PLIST, H5E_BADTYPE, "not an access list", -1); |
338 | 0 | if (H5FD_MULTI != H5Pget_driver(fapl_id)) |
339 | 0 | H5Epush_ret(__func__, H5E_ERR_CLS, H5E_PLIST, H5E_BADVALUE, "incorrect VFL driver", -1); |
340 | 0 | H5E_BEGIN_TRY |
341 | 0 | { |
342 | 0 | fa = (const H5FD_multi_fapl_t *)H5Pget_driver_info(fapl_id); |
343 | 0 | } |
344 | 0 | H5E_END_TRY |
345 | 0 | if (!fa || (H5P_FILE_ACCESS_DEFAULT == fapl_id)) { |
346 | 0 | if (H5FD_multi_populate_config(NULL, NULL, NULL, NULL, true, &default_fa) < 0) |
347 | 0 | H5Epush_ret(__func__, H5E_ERR_CLS, H5E_VFL, H5E_CANTSET, |
348 | 0 | "can't setup default driver configuration", -1); |
349 | 0 | fa = &default_fa; |
350 | 0 | } |
351 | | |
352 | 0 | if (memb_map) |
353 | 0 | memcpy(memb_map, fa->memb_map, H5FD_MEM_NTYPES * sizeof(H5FD_mem_t)); |
354 | 0 | if (memb_fapl) { |
355 | 0 | for (mt = H5FD_MEM_DEFAULT; mt < H5FD_MEM_NTYPES; mt = (H5FD_mem_t)(mt + 1)) { |
356 | 0 | if (fa->memb_fapl[mt] >= 0) |
357 | 0 | memb_fapl[mt] = H5Pcopy(fa->memb_fapl[mt]); |
358 | 0 | else |
359 | 0 | memb_fapl[mt] = fa->memb_fapl[mt]; /*default or bad ID*/ |
360 | 0 | } |
361 | 0 | } |
362 | 0 | if (memb_name) { |
363 | 0 | for (mt = H5FD_MEM_DEFAULT; mt < H5FD_MEM_NTYPES; mt = (H5FD_mem_t)(mt + 1)) { |
364 | 0 | if (fa->memb_name[mt]) |
365 | 0 | memb_name[mt] = my_strdup(fa->memb_name[mt]); |
366 | 0 | else |
367 | 0 | memb_name[mt] = NULL; |
368 | 0 | } |
369 | 0 | } |
370 | 0 | if (memb_addr) |
371 | 0 | memcpy(memb_addr, fa->memb_addr, H5FD_MEM_NTYPES * sizeof(haddr_t)); |
372 | 0 | if (relax) |
373 | 0 | *relax = fa->relax; |
374 | |
|
375 | 0 | return 0; |
376 | 0 | } |
377 | | |
378 | | /*------------------------------------------------------------------------- |
379 | | * Function: H5FD_split_populate_config |
380 | | * |
381 | | * Purpose: Populates a H5FD_multi_fapl_t structure with the provided |
382 | | * split driver values, supplying defaults where values are not |
383 | | * provided. |
384 | | * |
385 | | * Return: Non-negative on success/Negative on failure |
386 | | * |
387 | | *------------------------------------------------------------------------- |
388 | | */ |
389 | | static herr_t |
390 | | H5FD_split_populate_config(const char *meta_ext, hid_t meta_plist_id, const char *raw_ext, hid_t raw_plist_id, |
391 | | bool relax, H5FD_multi_fapl_t *fa_out) |
392 | 0 | { |
393 | 0 | static char |
394 | 0 | meta_name_g[H5FD_MULT_MAX_FILE_NAME_LEN]; /* Static scratch buffer to store metadata member name */ |
395 | 0 | static char |
396 | 0 | raw_name_g[H5FD_MULT_MAX_FILE_NAME_LEN]; /* Static scratch buffer to store raw data member name */ |
397 | 0 | const char *_memb_name[H5FD_MEM_NTYPES]; |
398 | 0 | H5FD_mem_t _memb_map[H5FD_MEM_NTYPES]; |
399 | 0 | hid_t _memb_fapl[H5FD_MEM_NTYPES]; |
400 | 0 | haddr_t _memb_addr[H5FD_MEM_NTYPES]; |
401 | 0 | herr_t ret_value = 0; |
402 | |
|
403 | 0 | assert(fa_out); |
404 | | |
405 | | /* Initialize */ |
406 | 0 | ALL_MEMBERS (mt) { |
407 | | /* Treat global heap as raw data, not metadata */ |
408 | 0 | _memb_map[mt] = ((mt == H5FD_MEM_DRAW || mt == H5FD_MEM_GHEAP) ? H5FD_MEM_DRAW : H5FD_MEM_SUPER); |
409 | 0 | _memb_fapl[mt] = H5P_DEFAULT; |
410 | 0 | _memb_name[mt] = NULL; |
411 | 0 | _memb_addr[mt] = HADDR_UNDEF; |
412 | 0 | } |
413 | 0 | END_MEMBERS |
414 | | |
415 | | /* The file access properties */ |
416 | 0 | _memb_fapl[H5FD_MEM_SUPER] = meta_plist_id; |
417 | 0 | _memb_fapl[H5FD_MEM_DRAW] = raw_plist_id; |
418 | | |
419 | | /* The names */ |
420 | | /* process meta filename */ |
421 | 0 | if (meta_ext) { |
422 | 0 | if (strstr(meta_ext, "%s")) { |
423 | | /* Note: this doesn't accommodate for when the '%s' in the user's |
424 | | * string is at a position >sizeof(meta_name) - QK & JK - 2013/01/17 |
425 | | */ |
426 | 0 | strncpy(meta_name_g, meta_ext, sizeof(meta_name_g)); |
427 | 0 | meta_name_g[sizeof(meta_name_g) - 1] = '\0'; |
428 | 0 | } |
429 | 0 | else |
430 | 0 | snprintf(meta_name_g, sizeof(meta_name_g), "%%s%s", meta_ext); |
431 | 0 | } |
432 | 0 | else { |
433 | 0 | strncpy(meta_name_g, "%s.meta", sizeof(meta_name_g)); |
434 | 0 | meta_name_g[sizeof(meta_name_g) - 1] = '\0'; |
435 | 0 | } |
436 | 0 | _memb_name[H5FD_MEM_SUPER] = meta_name_g; |
437 | | |
438 | | /* process raw filename */ |
439 | 0 | if (raw_ext) { |
440 | 0 | if (strstr(raw_ext, "%s")) { |
441 | | /* Note: this doesn't accommodate for when the '%s' in the user's |
442 | | * string is at a position >sizeof(raw_name) - QK & JK - 2013/01/17 |
443 | | */ |
444 | 0 | strncpy(raw_name_g, raw_ext, sizeof(raw_name_g)); |
445 | 0 | raw_name_g[sizeof(raw_name_g) - 1] = '\0'; |
446 | 0 | } |
447 | 0 | else |
448 | 0 | snprintf(raw_name_g, sizeof(raw_name_g), "%%s%s", raw_ext); |
449 | 0 | } |
450 | 0 | else { |
451 | 0 | strncpy(raw_name_g, "%s.raw", sizeof(raw_name_g)); |
452 | 0 | raw_name_g[sizeof(raw_name_g) - 1] = '\0'; |
453 | 0 | } |
454 | 0 | _memb_name[H5FD_MEM_DRAW] = raw_name_g; |
455 | | |
456 | | /* The sizes */ |
457 | 0 | _memb_addr[H5FD_MEM_SUPER] = 0; |
458 | 0 | _memb_addr[H5FD_MEM_DRAW] = HADDR_MAX / 2; |
459 | |
|
460 | 0 | ALL_MEMBERS (mt) { |
461 | | /* Map usage type */ |
462 | 0 | H5FD_mem_t mmt = _memb_map[mt]; |
463 | 0 | if (mmt < 0 || mmt >= H5FD_MEM_NTYPES) |
464 | 0 | H5Epush_ret(__func__, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADRANGE, "file resource type out of range", |
465 | 0 | -1); |
466 | | |
467 | | /* |
468 | | * All members of MEMB_FAPL must be either defaults or actual file |
469 | | * access property lists. |
470 | | */ |
471 | 0 | if (H5P_DEFAULT != _memb_fapl[mmt] && true != H5Pisa_class(_memb_fapl[mmt], H5P_FILE_ACCESS)) |
472 | 0 | H5Epush_ret(__func__, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, "file resource type incorrect", |
473 | 0 | -1); |
474 | | |
475 | | /* All names must be defined */ |
476 | 0 | if (!_memb_name[mmt] || !_memb_name[mmt][0]) |
477 | 0 | H5Epush_ret(__func__, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, "file resource type not set", -1); |
478 | 0 | } |
479 | 0 | END_MEMBERS |
480 | | |
481 | | /* |
482 | | * Initialize driver specific information. No need to copy it into the FA |
483 | | * struct since all members will be copied by H5Pset_driver(). |
484 | | */ |
485 | 0 | memset(fa_out, 0, sizeof(H5FD_multi_fapl_t)); |
486 | 0 | memcpy(fa_out->memb_map, _memb_map, H5FD_MEM_NTYPES * sizeof(H5FD_mem_t)); |
487 | 0 | memcpy(fa_out->memb_fapl, _memb_fapl, H5FD_MEM_NTYPES * sizeof(hid_t)); |
488 | 0 | memcpy(fa_out->memb_name, _memb_name, H5FD_MEM_NTYPES * sizeof(char *)); |
489 | 0 | memcpy(fa_out->memb_addr, _memb_addr, H5FD_MEM_NTYPES * sizeof(haddr_t)); |
490 | 0 | fa_out->relax = relax; |
491 | | |
492 | | /* Patch up H5P_DEFAULT property lists for members */ |
493 | 0 | ALL_MEMBERS (mt) { |
494 | 0 | if (fa_out->memb_fapl[mt] == H5P_DEFAULT) { |
495 | 0 | fa_out->memb_fapl[mt] = H5Pcreate(H5P_FILE_ACCESS); |
496 | 0 | if (H5Pset_fapl_sec2(fa_out->memb_fapl[mt]) < 0) |
497 | 0 | H5Epush_ret(__func__, H5E_ERR_CLS, H5E_INTERNAL, H5E_CANTSET, |
498 | 0 | "can't set sec2 driver on member FAPL", -1); |
499 | 0 | } |
500 | 0 | } |
501 | 0 | END_MEMBERS |
502 | | |
503 | 0 | return ret_value; |
504 | 0 | } |
505 | | |
506 | | /*------------------------------------------------------------------------- |
507 | | * Function: H5FD_multi_populate_config |
508 | | * |
509 | | * Purpose: Populates a H5FD_multi_fapl_t structure with the provided |
510 | | * values, supplying defaults where values are not provided. |
511 | | * |
512 | | * Return: Non-negative on success/Negative on failure |
513 | | * |
514 | | *------------------------------------------------------------------------- |
515 | | */ |
516 | | static herr_t |
517 | | H5FD_multi_populate_config(const H5FD_mem_t *memb_map, const hid_t *memb_fapl, const char *const *memb_name, |
518 | | const haddr_t *memb_addr, bool relax, H5FD_multi_fapl_t *fa_out) |
519 | 0 | { |
520 | 0 | static const char *letters = "Xsbrglo"; |
521 | 0 | static char _memb_name_g[H5FD_MEM_NTYPES][16]; /* Static scratch buffer to store member names */ |
522 | 0 | H5FD_mem_t mt, mmt; |
523 | 0 | H5FD_mem_t _memb_map[H5FD_MEM_NTYPES]; |
524 | 0 | hid_t _memb_fapl[H5FD_MEM_NTYPES]; |
525 | 0 | const char *_memb_name_ptrs[H5FD_MEM_NTYPES]; |
526 | 0 | haddr_t _memb_addr[H5FD_MEM_NTYPES]; |
527 | 0 | herr_t ret_value = 0; |
528 | |
|
529 | 0 | assert(fa_out); |
530 | |
|
531 | 0 | if (!memb_map) { |
532 | 0 | for (mt = H5FD_MEM_DEFAULT; mt < H5FD_MEM_NTYPES; mt = (H5FD_mem_t)(mt + 1)) |
533 | 0 | _memb_map[mt] = H5FD_MEM_DEFAULT; |
534 | 0 | memb_map = _memb_map; |
535 | 0 | } |
536 | 0 | if (!memb_fapl) { |
537 | 0 | for (mt = H5FD_MEM_DEFAULT; mt < H5FD_MEM_NTYPES; mt = (H5FD_mem_t)(mt + 1)) { |
538 | 0 | _memb_fapl[mt] = H5Pcreate(H5P_FILE_ACCESS); |
539 | 0 | if (H5Pset_fapl_sec2(_memb_fapl[mt]) < 0) |
540 | 0 | H5Epush_ret(__func__, H5E_ERR_CLS, H5E_INTERNAL, H5E_CANTSET, |
541 | 0 | "can't set sec2 driver on member FAPL", -1); |
542 | 0 | } |
543 | 0 | memb_fapl = _memb_fapl; |
544 | 0 | } |
545 | 0 | if (!memb_name) { |
546 | 0 | assert(strlen(letters) == H5FD_MEM_NTYPES); |
547 | 0 | for (mt = H5FD_MEM_DEFAULT; mt < H5FD_MEM_NTYPES; mt = (H5FD_mem_t)(mt + 1)) { |
548 | 0 | snprintf(_memb_name_g[mt], 16, "%%s-%c.h5", letters[mt]); |
549 | 0 | _memb_name_ptrs[mt] = _memb_name_g[mt]; |
550 | 0 | } |
551 | 0 | memb_name = _memb_name_ptrs; |
552 | 0 | } |
553 | 0 | if (!memb_addr) { |
554 | 0 | for (mt = H5FD_MEM_DEFAULT; mt < H5FD_MEM_NTYPES; mt = (H5FD_mem_t)(mt + 1)) |
555 | 0 | _memb_addr[mt] = (hsize_t)(mt ? (mt - 1) : 0) * (HADDR_MAX / (H5FD_MEM_NTYPES - 1)); |
556 | 0 | memb_addr = _memb_addr; |
557 | 0 | } |
558 | |
|
559 | 0 | for (mt = H5FD_MEM_DEFAULT; mt < H5FD_MEM_NTYPES; mt = (H5FD_mem_t)(mt + 1)) { |
560 | | /* Map usage type */ |
561 | 0 | mmt = memb_map[mt]; |
562 | 0 | if (mmt < 0 || mmt >= H5FD_MEM_NTYPES) |
563 | 0 | H5Epush_ret(__func__, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADRANGE, "file resource type out of range", |
564 | 0 | -1); |
565 | 0 | if (H5FD_MEM_DEFAULT == mmt) |
566 | 0 | mmt = mt; |
567 | | |
568 | | /* |
569 | | * All members of MEMB_FAPL must be either defaults or actual file |
570 | | * access property lists. |
571 | | */ |
572 | 0 | if (H5P_DEFAULT != memb_fapl[mmt] && true != H5Pisa_class(memb_fapl[mmt], H5P_FILE_ACCESS)) |
573 | 0 | H5Epush_ret(__func__, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, "file resource type incorrect", |
574 | 0 | -1); |
575 | | |
576 | | /* All names must be defined */ |
577 | 0 | if (!memb_name[mmt] || !memb_name[mmt][0]) |
578 | 0 | H5Epush_ret(__func__, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, "file resource type not set", -1); |
579 | 0 | } |
580 | | |
581 | | /* |
582 | | * Initialize driver specific information. No need to copy it into the FA |
583 | | * struct since all members will be copied by H5Pset_driver(). |
584 | | */ |
585 | 0 | memset(fa_out, 0, sizeof(H5FD_multi_fapl_t)); |
586 | 0 | memcpy(fa_out->memb_map, memb_map, H5FD_MEM_NTYPES * sizeof(H5FD_mem_t)); |
587 | 0 | memcpy(fa_out->memb_fapl, memb_fapl, H5FD_MEM_NTYPES * sizeof(hid_t)); |
588 | 0 | memcpy(fa_out->memb_name, memb_name, H5FD_MEM_NTYPES * sizeof(char *)); |
589 | 0 | memcpy(fa_out->memb_addr, memb_addr, H5FD_MEM_NTYPES * sizeof(haddr_t)); |
590 | 0 | fa_out->relax = relax; |
591 | | |
592 | | /* Patch up H5P_DEFAULT property lists for members */ |
593 | 0 | for (mt = H5FD_MEM_DEFAULT; mt < H5FD_MEM_NTYPES; mt = (H5FD_mem_t)(mt + 1)) { |
594 | 0 | if (fa_out->memb_fapl[mt] == H5P_DEFAULT) { |
595 | 0 | fa_out->memb_fapl[mt] = H5Pcreate(H5P_FILE_ACCESS); |
596 | 0 | if (H5Pset_fapl_sec2(fa_out->memb_fapl[mt]) < 0) |
597 | 0 | H5Epush_ret(__func__, H5E_ERR_CLS, H5E_INTERNAL, H5E_CANTSET, |
598 | 0 | "can't set sec2 driver on member FAPL", -1); |
599 | 0 | } |
600 | 0 | } |
601 | | |
602 | 0 | return ret_value; |
603 | 0 | } /* end H5FD_multi_populate_config() */ |
604 | | |
605 | | /*------------------------------------------------------------------------- |
606 | | * Function: H5FD_multi_sb_size |
607 | | * |
608 | | * Purpose: Returns the size of the private information to be stored in |
609 | | * the superblock. |
610 | | * |
611 | | * Return: Success: The super block driver data size. |
612 | | * |
613 | | * Failure: never fails |
614 | | * |
615 | | *------------------------------------------------------------------------- |
616 | | */ |
617 | | static hsize_t |
618 | | H5FD_multi_sb_size(H5FD_t *_file) |
619 | 0 | { |
620 | 0 | H5FD_multi_t *file = (H5FD_multi_t *)_file; |
621 | 0 | unsigned nseen = 0; |
622 | 0 | hsize_t nbytes = 8; /*size of header*/ |
623 | | |
624 | | /* Clear the error stack */ |
625 | 0 | H5Eclear2(H5E_DEFAULT); |
626 | | |
627 | | /* How many unique files? */ |
628 | 0 | UNIQUE_MEMBERS (file->fa.memb_map, mt) { |
629 | 0 | nseen++; |
630 | 0 | } |
631 | 0 | END_MEMBERS |
632 | | |
633 | | /* Addresses and EOA markers */ |
634 | 0 | nbytes += nseen * 2 * 8; |
635 | | |
636 | | /* Name templates */ |
637 | 0 | UNIQUE_MEMBERS (file->fa.memb_map, mt) { |
638 | 0 | size_t n = strlen(file->fa.memb_name[mt]) + 1; |
639 | 0 | nbytes += (n + 7) & ~((size_t)0x0007); |
640 | 0 | } |
641 | 0 | END_MEMBERS |
642 | |
|
643 | 0 | return nbytes; |
644 | 0 | } |
645 | | |
646 | | /*------------------------------------------------------------------------- |
647 | | * Function: H5FD_multi_sb_encode |
648 | | * |
649 | | * Purpose: Encode driver information for the superblock. The NAME |
650 | | * argument is a nine-byte buffer which will be initialized with |
651 | | * an eight-character name/version number and null termination. |
652 | | * |
653 | | * The encoding is a six-byte member mapping followed two bytes |
654 | | * which are unused. For each unique file in usage-type order |
655 | | * encode all the starting addresses as unsigned 64-bit integers, |
656 | | * then all the EOA values as unsigned 64-bit integers, then all |
657 | | * the template names as null terminated strings which are |
658 | | * multiples of 8 characters. |
659 | | * |
660 | | * Return: Success: 0 |
661 | | * |
662 | | * Failure: -1 |
663 | | * |
664 | | *------------------------------------------------------------------------- |
665 | | */ |
666 | | static herr_t |
667 | | H5FD_multi_sb_encode(H5FD_t *_file, char *name /*out*/, unsigned char *buf /*out*/) |
668 | 0 | { |
669 | 0 | H5FD_multi_t *file = (H5FD_multi_t *)_file; |
670 | 0 | haddr_t memb_eoa; |
671 | 0 | unsigned char *p; |
672 | 0 | size_t nseen; |
673 | 0 | size_t i; |
674 | 0 | H5FD_mem_t m; |
675 | | |
676 | | /* Clear the error stack */ |
677 | 0 | H5Eclear2(H5E_DEFAULT); |
678 | | |
679 | | /* Name and version number */ |
680 | 0 | strncpy(name, "NCSAmult", (size_t)9); |
681 | 0 | name[8] = '\0'; |
682 | |
|
683 | 0 | assert(7 == H5FD_MEM_NTYPES); |
684 | |
|
685 | 0 | for (m = H5FD_MEM_SUPER; m < H5FD_MEM_NTYPES; m = (H5FD_mem_t)(m + 1)) { |
686 | 0 | buf[m - 1] = (unsigned char)file->fa.memb_map[m]; |
687 | 0 | } |
688 | 0 | buf[6] = 0; |
689 | 0 | buf[7] = 0; |
690 | | |
691 | | /* |
692 | | * Copy the starting addresses and EOA values into the buffer in order of |
693 | | * usage type but only for types which map to something unique. |
694 | | */ |
695 | | |
696 | | /* Encode all starting addresses and EOA values */ |
697 | 0 | nseen = 0; |
698 | 0 | p = buf + 8; |
699 | 0 | assert(sizeof(haddr_t) <= 8); |
700 | 0 | UNIQUE_MEMBERS (file->fa.memb_map, mt) { |
701 | 0 | memcpy(p, &(file->fa.memb_addr[mt]), sizeof(haddr_t)); |
702 | 0 | p += sizeof(haddr_t); |
703 | 0 | memb_eoa = H5FDget_eoa(file->memb[mt], mt); |
704 | 0 | memcpy(p, &memb_eoa, sizeof(haddr_t)); |
705 | 0 | p += sizeof(haddr_t); |
706 | 0 | nseen++; |
707 | 0 | } |
708 | 0 | END_MEMBERS |
709 | 0 | if (H5Tconvert(H5T_NATIVE_HADDR, H5T_STD_U64LE, nseen * 2, buf + 8, NULL, H5P_DEFAULT) < 0) |
710 | 0 | H5Epush_ret(__func__, H5E_ERR_CLS, H5E_DATATYPE, H5E_CANTCONVERT, "can't convert superblock info", |
711 | 0 | -1); |
712 | | |
713 | | /* Encode all name templates */ |
714 | 0 | p = buf + 8 + nseen * 2 * 8; |
715 | 0 | UNIQUE_MEMBERS (file->fa.memb_map, mt) { |
716 | 0 | size_t n = strlen(file->fa.memb_name[mt]) + 1; |
717 | 0 | strcpy((char *)p, file->fa.memb_name[mt]); |
718 | 0 | p += n; |
719 | 0 | for (i = n; i % 8; i++) |
720 | 0 | *p++ = '\0'; |
721 | 0 | } |
722 | 0 | END_MEMBERS |
723 | |
|
724 | 0 | return 0; |
725 | 0 | } /* end H5FD_multi_sb_encode() */ |
726 | | |
727 | | /*------------------------------------------------------------------------- |
728 | | * Function: H5FD_multi_sb_decode |
729 | | * |
730 | | * Purpose: Decodes the superblock information for this driver. The NAME |
731 | | * argument is the eight-character (plus null termination) name |
732 | | * stored in the file. |
733 | | * |
734 | | * The FILE argument is updated according to the information in |
735 | | * the superblock. This may mean that some member files are |
736 | | * closed and others are opened. |
737 | | * |
738 | | * Return: Success: 0 |
739 | | * |
740 | | * Failure: -1 |
741 | | * |
742 | | *------------------------------------------------------------------------- |
743 | | */ |
744 | | static herr_t |
745 | | H5FD_multi_sb_decode(H5FD_t *_file, const char *name, const unsigned char *buf) |
746 | 0 | { |
747 | 0 | H5FD_multi_t *file = (H5FD_multi_t *)_file; |
748 | 0 | char x[2 * H5FD_MEM_NTYPES * 8]; |
749 | 0 | H5FD_mem_t map[H5FD_MEM_NTYPES]; |
750 | 0 | int i; |
751 | 0 | size_t nseen = 0; |
752 | 0 | bool map_changed = false; |
753 | 0 | bool in_use[H5FD_MEM_NTYPES]; |
754 | 0 | const char *memb_name[H5FD_MEM_NTYPES]; |
755 | 0 | haddr_t memb_addr[H5FD_MEM_NTYPES]; |
756 | 0 | haddr_t memb_eoa[H5FD_MEM_NTYPES]; |
757 | 0 | haddr_t *ap; |
758 | | |
759 | | /* Clear the error stack */ |
760 | 0 | H5Eclear2(H5E_DEFAULT); |
761 | | |
762 | | /* Make sure the name/version number is correct */ |
763 | 0 | if (strcmp(name, "NCSAmult") != 0) |
764 | 0 | H5Epush_ret(__func__, H5E_ERR_CLS, H5E_FILE, H5E_BADVALUE, "invalid multi superblock", -1); |
765 | | |
766 | | /* Set default values */ |
767 | 0 | ALL_MEMBERS (mt) { |
768 | 0 | memb_addr[mt] = HADDR_UNDEF; |
769 | 0 | memb_eoa[mt] = HADDR_UNDEF; |
770 | 0 | memb_name[mt] = NULL; |
771 | 0 | } |
772 | 0 | END_MEMBERS |
773 | | |
774 | | /* |
775 | | * Read the map and count the unique members. |
776 | | */ |
777 | 0 | memset(map, 0, sizeof map); |
778 | |
|
779 | 0 | for (i = 0; i < 6; i++) { |
780 | 0 | map[i + 1] = (H5FD_mem_t)buf[i]; |
781 | 0 | if (file->fa.memb_map[i + 1] != map[i + 1]) |
782 | 0 | map_changed = true; |
783 | 0 | } |
784 | |
|
785 | 0 | UNIQUE_MEMBERS (map, mt) { |
786 | 0 | nseen++; |
787 | 0 | } |
788 | 0 | END_MEMBERS |
789 | 0 | buf += 8; |
790 | | |
791 | | /* Decode Address and EOA values */ |
792 | 0 | assert(sizeof(haddr_t) <= 8); |
793 | 0 | memcpy(x, buf, (nseen * 2 * 8)); |
794 | 0 | buf += nseen * 2 * 8; |
795 | 0 | if (H5Tconvert(H5T_STD_U64LE, H5T_NATIVE_HADDR, nseen * 2, x, NULL, H5P_DEFAULT) < 0) |
796 | 0 | H5Epush_ret(__func__, H5E_ERR_CLS, H5E_DATATYPE, H5E_CANTCONVERT, "can't convert superblock info", |
797 | 0 | -1); |
798 | 0 | ap = (haddr_t *)((void *)x); /* Extra (void *) cast to quiet "cast to create alignment" warning - |
799 | | 2019/07/05, QAK */ |
800 | 0 | UNIQUE_MEMBERS (map, mt) { |
801 | 0 | memb_addr[_unmapped] = *ap++; |
802 | 0 | memb_eoa[_unmapped] = *ap++; |
803 | 0 | } |
804 | 0 | END_MEMBERS |
805 | | |
806 | | /* Decode name templates */ |
807 | 0 | UNIQUE_MEMBERS (map, mt) { |
808 | 0 | size_t n = strlen((const char *)buf) + 1; |
809 | 0 | memb_name[_unmapped] = (const char *)buf; |
810 | 0 | buf += (n + 7) & ~((unsigned)0x0007); |
811 | 0 | } |
812 | 0 | END_MEMBERS |
813 | | |
814 | | /* |
815 | | * Use the mapping saved in the superblock in preference to the one |
816 | | * already set for the file. Since we may have opened files which are no |
817 | | * longer needed we should close all those files. We'll open the new |
818 | | * files at the end. |
819 | | */ |
820 | 0 | if (map_changed) { |
821 | | /* Commit map */ |
822 | 0 | ALL_MEMBERS (mt) { |
823 | 0 | file->fa.memb_map[mt] = map[mt]; |
824 | 0 | } |
825 | 0 | END_MEMBERS |
826 | | |
827 | | /* Close files which are unused now */ |
828 | 0 | memset(in_use, 0, sizeof in_use); |
829 | 0 | UNIQUE_MEMBERS (map, mt) { |
830 | 0 | in_use[mt] = true; |
831 | 0 | } |
832 | 0 | END_MEMBERS |
833 | 0 | ALL_MEMBERS (mt) { |
834 | 0 | if (!in_use[mt] && file->memb[mt]) { |
835 | 0 | (void)H5FDclose(file->memb[mt]); |
836 | 0 | file->memb[mt] = NULL; |
837 | 0 | } |
838 | 0 | file->fa.memb_map[mt] = map[mt]; |
839 | 0 | } |
840 | 0 | END_MEMBERS |
841 | 0 | } |
842 | | |
843 | | /* Commit member starting addresses and name templates */ |
844 | 0 | ALL_MEMBERS (mt) { |
845 | 0 | file->fa.memb_addr[mt] = memb_addr[mt]; |
846 | 0 | if (memb_name[mt]) { |
847 | 0 | if (file->fa.memb_name[mt]) |
848 | 0 | free(file->fa.memb_name[mt]); |
849 | 0 | file->fa.memb_name[mt] = my_strdup(memb_name[mt]); |
850 | 0 | } |
851 | 0 | } |
852 | 0 | END_MEMBERS |
853 | 0 | if (compute_next(file) < 0) |
854 | 0 | H5Epush_ret(__func__, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, "compute_next() failed", -1); |
855 | | |
856 | | /* Open all necessary files */ |
857 | 0 | if (open_members(file) < 0) |
858 | 0 | H5Epush_ret(__func__, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, "open_members() failed", -1); |
859 | | |
860 | | /* Set the EOA marker for all open files */ |
861 | 0 | UNIQUE_MEMBERS (file->fa.memb_map, mt) { |
862 | 0 | if (file->memb[mt]) |
863 | 0 | if (H5FDset_eoa(file->memb[mt], mt, memb_eoa[mt]) < 0) |
864 | 0 | H5Epush_ret(__func__, H5E_ERR_CLS, H5E_INTERNAL, H5E_CANTSET, "set_eoa() failed", -1); |
865 | | |
866 | | /* Save the individual EOAs in one place for later comparison (in H5FD_multi_set_eoa) |
867 | | */ |
868 | 0 | file->memb_eoa[mt] = memb_eoa[mt]; |
869 | 0 | } |
870 | 0 | END_MEMBERS |
871 | | |
872 | 0 | return 0; |
873 | 0 | } /* end H5FD_multi_sb_decode() */ |
874 | | |
875 | | /*------------------------------------------------------------------------- |
876 | | * Function: H5FD_multi_fapl_get |
877 | | * |
878 | | * Purpose: Returns a file access property list which indicates how the |
879 | | * specified file is being accessed. The return list could be |
880 | | * used to access another file the same way. |
881 | | * |
882 | | * Return: Success: Ptr to new file access property list with all |
883 | | * members copied from the file struct. |
884 | | * |
885 | | * Failure: NULL |
886 | | * |
887 | | *------------------------------------------------------------------------- |
888 | | */ |
889 | | static void * |
890 | | H5FD_multi_fapl_get(H5FD_t *_file) |
891 | 0 | { |
892 | 0 | H5FD_multi_t *file = (H5FD_multi_t *)_file; |
893 | | |
894 | | /* Clear the error stack */ |
895 | 0 | H5Eclear2(H5E_DEFAULT); |
896 | |
|
897 | 0 | return H5FD_multi_fapl_copy(&(file->fa)); |
898 | 0 | } |
899 | | |
900 | | /*------------------------------------------------------------------------- |
901 | | * Function: H5FD_multi_fapl_copy |
902 | | * |
903 | | * Purpose: Copies the multi-specific file access properties. |
904 | | * |
905 | | * Return: Success: Ptr to a new property list |
906 | | * |
907 | | * Failure: NULL |
908 | | * |
909 | | *------------------------------------------------------------------------- |
910 | | */ |
911 | | static void * |
912 | | H5FD_multi_fapl_copy(const void *_old_fa) |
913 | 0 | { |
914 | 0 | const H5FD_multi_fapl_t *old_fa = (const H5FD_multi_fapl_t *)_old_fa; |
915 | 0 | H5FD_multi_fapl_t *new_fa = (H5FD_multi_fapl_t *)calloc(1, sizeof(H5FD_multi_fapl_t)); |
916 | 0 | int nerrors = 0; |
917 | |
|
918 | 0 | assert(new_fa); |
919 | | |
920 | | /* Clear the error stack */ |
921 | 0 | H5Eclear2(H5E_DEFAULT); |
922 | |
|
923 | 0 | memcpy(new_fa, old_fa, sizeof(H5FD_multi_fapl_t)); |
924 | 0 | ALL_MEMBERS (mt) { |
925 | 0 | if (old_fa->memb_fapl[mt] >= 0) { |
926 | 0 | if (H5Iinc_ref(old_fa->memb_fapl[mt]) < 0) { |
927 | 0 | nerrors++; |
928 | 0 | break; |
929 | 0 | } |
930 | 0 | new_fa->memb_fapl[mt] = old_fa->memb_fapl[mt]; |
931 | 0 | } |
932 | 0 | if (old_fa->memb_name[mt]) { |
933 | 0 | new_fa->memb_name[mt] = my_strdup(old_fa->memb_name[mt]); |
934 | 0 | if (NULL == new_fa->memb_name[mt]) { |
935 | 0 | nerrors++; |
936 | 0 | break; |
937 | 0 | } |
938 | 0 | } |
939 | 0 | } |
940 | 0 | END_MEMBERS |
941 | |
|
942 | 0 | if (nerrors) { |
943 | 0 | ALL_MEMBERS (mt) { |
944 | 0 | if (new_fa->memb_fapl[mt] >= 0) |
945 | 0 | (void)H5Idec_ref(new_fa->memb_fapl[mt]); |
946 | 0 | if (new_fa->memb_name[mt]) |
947 | 0 | free(new_fa->memb_name[mt]); |
948 | 0 | } |
949 | 0 | END_MEMBERS |
950 | 0 | free(new_fa); |
951 | 0 | H5Epush_ret(__func__, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, "can't release object on error", NULL); |
952 | 0 | } |
953 | 0 | return new_fa; |
954 | 0 | } |
955 | | |
956 | | /*------------------------------------------------------------------------- |
957 | | * Function: H5FD_multi_fapl_free |
958 | | * |
959 | | * Purpose: Frees the multi-specific file access properties. |
960 | | * |
961 | | * Return: Success: 0 |
962 | | * |
963 | | * Failure: -1 |
964 | | * |
965 | | *------------------------------------------------------------------------- |
966 | | */ |
967 | | static herr_t |
968 | | H5FD_multi_fapl_free(void *_fa) |
969 | 0 | { |
970 | 0 | H5FD_multi_fapl_t *fa = (H5FD_multi_fapl_t *)_fa; |
971 | | |
972 | | /* Clear the error stack */ |
973 | 0 | H5Eclear2(H5E_DEFAULT); |
974 | |
|
975 | 0 | ALL_MEMBERS (mt) { |
976 | 0 | if (fa->memb_fapl[mt] >= 0) |
977 | 0 | if (H5Idec_ref(fa->memb_fapl[mt]) < 0) |
978 | 0 | H5Epush_ret(__func__, H5E_ERR_CLS, H5E_FILE, H5E_CANTCLOSEOBJ, "can't close property list", |
979 | 0 | -1); |
980 | 0 | if (fa->memb_name[mt]) |
981 | 0 | free(fa->memb_name[mt]); |
982 | 0 | } |
983 | 0 | END_MEMBERS |
984 | 0 | free(fa); |
985 | |
|
986 | 0 | return 0; |
987 | 0 | } |
988 | | |
989 | | /*------------------------------------------------------------------------- |
990 | | * Function: H5FD_multi_open |
991 | | * |
992 | | * Purpose: Creates and/or opens a multi HDF5 file. |
993 | | * |
994 | | * Return: Success: A pointer to a new file data structure. The |
995 | | * public fields will be initialized by the |
996 | | * caller, which is always H5FD_open(). |
997 | | * |
998 | | * Failure: NULL |
999 | | * |
1000 | | *------------------------------------------------------------------------- |
1001 | | */ |
1002 | | static H5FD_t * |
1003 | | H5FD_multi_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr) |
1004 | 0 | { |
1005 | 0 | H5FD_multi_t *file = NULL; |
1006 | 0 | hid_t close_fapl = -1; |
1007 | 0 | const H5FD_multi_fapl_t *fa; |
1008 | 0 | H5FD_mem_t m; |
1009 | | |
1010 | | /* Clear the error stack */ |
1011 | 0 | H5Eclear2(H5E_DEFAULT); |
1012 | | |
1013 | | /* Check arguments */ |
1014 | 0 | if (!name || !*name) |
1015 | 0 | H5Epush_ret(__func__, H5E_ERR_CLS, H5E_ARGS, H5E_BADVALUE, "invalid file name", NULL); |
1016 | 0 | if (0 == maxaddr || HADDR_UNDEF == maxaddr) |
1017 | 0 | H5Epush_ret(__func__, H5E_ERR_CLS, H5E_ARGS, H5E_BADRANGE, "bogus maxaddr", NULL); |
1018 | | |
1019 | | /* |
1020 | | * Initialize the file from the file access properties, using default |
1021 | | * values if necessary. Make sure to use CALLOC here because the code |
1022 | | * in H5FD_multi_set_eoa depends on the proper initialization of memb_eoa |
1023 | | * in H5FD_multi_t. |
1024 | | */ |
1025 | 0 | if (NULL == (file = (H5FD_multi_t *)calloc((size_t)1, sizeof(H5FD_multi_t)))) |
1026 | 0 | H5Epush_ret(__func__, H5E_ERR_CLS, H5E_RESOURCE, H5E_NOSPACE, "memory allocation failed", NULL); |
1027 | 0 | H5E_BEGIN_TRY |
1028 | 0 | { |
1029 | 0 | fa = (const H5FD_multi_fapl_t *)H5Pget_driver_info(fapl_id); |
1030 | 0 | } |
1031 | 0 | H5E_END_TRY |
1032 | 0 | if (!fa || (H5P_FILE_ACCESS_DEFAULT == fapl_id) || (H5FD_MULTI != H5Pget_driver(fapl_id))) { |
1033 | 0 | char *env = getenv(HDF5_DRIVER); |
1034 | |
|
1035 | 0 | close_fapl = fapl_id = H5Pcreate(H5P_FILE_ACCESS); |
1036 | 0 | if (env && !strcmp(env, "split")) { |
1037 | 0 | if (H5Pset_fapl_split(fapl_id, NULL, H5P_DEFAULT, NULL, H5P_DEFAULT) < 0) |
1038 | 0 | H5Epush_goto(__func__, H5E_ERR_CLS, H5E_FILE, H5E_CANTSET, "can't set property value", error); |
1039 | 0 | } |
1040 | 0 | else { |
1041 | 0 | if (H5Pset_fapl_multi(fapl_id, NULL, NULL, NULL, NULL, true) < 0) |
1042 | 0 | H5Epush_goto(__func__, H5E_ERR_CLS, H5E_FILE, H5E_CANTSET, "can't set property value", error); |
1043 | 0 | } |
1044 | | |
1045 | 0 | fa = (const H5FD_multi_fapl_t *)H5Pget_driver_info(fapl_id); |
1046 | 0 | } |
1047 | 0 | assert(fa); |
1048 | 0 | ALL_MEMBERS (mt) { |
1049 | 0 | file->fa.memb_map[mt] = fa->memb_map[mt]; |
1050 | 0 | file->fa.memb_addr[mt] = fa->memb_addr[mt]; |
1051 | 0 | if (fa->memb_fapl[mt] >= 0) |
1052 | 0 | H5Iinc_ref(fa->memb_fapl[mt]); |
1053 | 0 | file->fa.memb_fapl[mt] = fa->memb_fapl[mt]; |
1054 | 0 | if (fa->memb_name[mt]) |
1055 | 0 | file->fa.memb_name[mt] = my_strdup(fa->memb_name[mt]); |
1056 | 0 | else |
1057 | 0 | file->fa.memb_name[mt] = NULL; |
1058 | 0 | } |
1059 | 0 | END_MEMBERS |
1060 | 0 | file->fa.relax = fa->relax; |
1061 | 0 | file->flags = flags; |
1062 | 0 | file->name = my_strdup(name); |
1063 | 0 | if (close_fapl >= 0) |
1064 | 0 | if (H5Pclose(close_fapl) < 0) |
1065 | 0 | H5Epush_goto(__func__, H5E_ERR_CLS, H5E_FILE, H5E_CANTCLOSEOBJ, "can't close property list", |
1066 | 0 | error); |
1067 | | |
1068 | | /* Compute derived properties and open member files */ |
1069 | 0 | if (compute_next(file) < 0) |
1070 | 0 | H5Epush_goto(__func__, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, "compute_next() failed", error); |
1071 | 0 | if (open_members(file) < 0) |
1072 | 0 | H5Epush_goto(__func__, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, "open_members() failed", error); |
1073 | | |
1074 | | /* We must have opened at least the superblock file */ |
1075 | 0 | if (H5FD_MEM_DEFAULT == (m = file->fa.memb_map[H5FD_MEM_SUPER])) |
1076 | 0 | m = H5FD_MEM_SUPER; |
1077 | 0 | if (NULL == file->memb[m]) |
1078 | 0 | goto error; |
1079 | | |
1080 | 0 | return (H5FD_t *)file; |
1081 | | |
1082 | 0 | error: |
1083 | | /* Cleanup and fail */ |
1084 | 0 | if (file) { |
1085 | 0 | ALL_MEMBERS (mt) { |
1086 | 0 | if (file->memb[mt]) |
1087 | 0 | (void)H5FDclose(file->memb[mt]); |
1088 | 0 | if (file->fa.memb_fapl[mt] >= 0) |
1089 | 0 | (void)H5Idec_ref(file->fa.memb_fapl[mt]); |
1090 | 0 | if (file->fa.memb_name[mt]) |
1091 | 0 | free(file->fa.memb_name[mt]); |
1092 | 0 | } |
1093 | 0 | END_MEMBERS |
1094 | 0 | if (file->name) |
1095 | 0 | free(file->name); |
1096 | 0 | free(file); |
1097 | 0 | } |
1098 | 0 | return NULL; |
1099 | 0 | } |
1100 | | |
1101 | | /*------------------------------------------------------------------------- |
1102 | | * Function: H5FD_multi_close |
1103 | | * |
1104 | | * Purpose: Closes a multi file. |
1105 | | * |
1106 | | * Return: Success: Non-negative |
1107 | | * |
1108 | | * Failure: Negative with as many members closed as |
1109 | | * possible. The only subsequent operation |
1110 | | * permitted on the file is a close operation. |
1111 | | * |
1112 | | *------------------------------------------------------------------------- |
1113 | | */ |
1114 | | static herr_t |
1115 | | H5FD_multi_close(H5FD_t *_file) |
1116 | 0 | { |
1117 | 0 | H5FD_multi_t *file = (H5FD_multi_t *)_file; |
1118 | 0 | int nerrors = 0; |
1119 | | |
1120 | | /* Clear the error stack */ |
1121 | 0 | H5Eclear2(H5E_DEFAULT); |
1122 | | |
1123 | | /* Close as many members as possible */ |
1124 | 0 | ALL_MEMBERS (mt) { |
1125 | 0 | if (file->memb[mt]) { |
1126 | 0 | if (H5FDclose(file->memb[mt]) < 0) { |
1127 | 0 | nerrors++; |
1128 | 0 | } |
1129 | 0 | else { |
1130 | 0 | file->memb[mt] = NULL; |
1131 | 0 | } |
1132 | 0 | } |
1133 | 0 | } |
1134 | 0 | END_MEMBERS |
1135 | 0 | if (nerrors) |
1136 | 0 | H5Epush_ret(__func__, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, "error closing member files", -1); |
1137 | | |
1138 | | /* Clean up other stuff */ |
1139 | 0 | ALL_MEMBERS (mt) { |
1140 | 0 | if (file->fa.memb_fapl[mt] >= 0) |
1141 | 0 | (void)H5Idec_ref(file->fa.memb_fapl[mt]); |
1142 | 0 | if (file->fa.memb_name[mt]) |
1143 | 0 | free(file->fa.memb_name[mt]); |
1144 | 0 | } |
1145 | 0 | END_MEMBERS |
1146 | |
|
1147 | 0 | free(file->name); |
1148 | 0 | free(file); |
1149 | 0 | return 0; |
1150 | 0 | } |
1151 | | |
1152 | | /*------------------------------------------------------------------------- |
1153 | | * Function: H5FD_multi_cmp |
1154 | | * |
1155 | | * Purpose: Compares two file families to see if they are the same. It |
1156 | | * does this by comparing the first common member of the two |
1157 | | * families. If the families have no members in common then the |
1158 | | * file with the earliest member is smaller than the other file. |
1159 | | * We abort if neither file has any members. |
1160 | | * |
1161 | | * Return: Success: like strcmp() |
1162 | | * |
1163 | | * Failure: never fails (arguments were checked by th caller). |
1164 | | * |
1165 | | *------------------------------------------------------------------------- |
1166 | | */ |
1167 | | static int |
1168 | | H5FD_multi_cmp(const H5FD_t *_f1, const H5FD_t *_f2) |
1169 | 0 | { |
1170 | 0 | const H5FD_multi_t *f1 = (const H5FD_multi_t *)_f1; |
1171 | 0 | const H5FD_multi_t *f2 = (const H5FD_multi_t *)_f2; |
1172 | 0 | H5FD_mem_t out_mt = H5FD_MEM_DEFAULT; |
1173 | 0 | int cmp = 0; |
1174 | | |
1175 | | /* Clear the error stack */ |
1176 | 0 | H5Eclear2(H5E_DEFAULT); |
1177 | |
|
1178 | 0 | ALL_MEMBERS (mt) { |
1179 | 0 | out_mt = mt; |
1180 | 0 | if (f1->memb[mt] && f2->memb[mt]) |
1181 | 0 | break; |
1182 | 0 | if (!cmp) { |
1183 | 0 | if (f1->memb[mt]) |
1184 | 0 | cmp = -1; |
1185 | 0 | else if (f2->memb[mt]) |
1186 | 0 | cmp = 1; |
1187 | 0 | } |
1188 | 0 | } |
1189 | 0 | END_MEMBERS |
1190 | 0 | assert(cmp || out_mt < H5FD_MEM_NTYPES); |
1191 | 0 | if (out_mt >= H5FD_MEM_NTYPES) |
1192 | 0 | return cmp; |
1193 | | |
1194 | 0 | return H5FDcmp(f1->memb[out_mt], f2->memb[out_mt]); |
1195 | 0 | } |
1196 | | |
1197 | | /*------------------------------------------------------------------------- |
1198 | | * Function: H5FD_multi_query |
1199 | | * |
1200 | | * Purpose: Set the flags that this VFL driver is capable of supporting. |
1201 | | * (listed in H5FDpublic.h) |
1202 | | * |
1203 | | * Return: Success: non-negative |
1204 | | * |
1205 | | * Failure: negative |
1206 | | * |
1207 | | *------------------------------------------------------------------------- |
1208 | | */ |
1209 | | static herr_t |
1210 | | H5FD_multi_query(const H5FD_t *_f, unsigned long *flags /* out */) |
1211 | 0 | { |
1212 | | /* Shut compiler up */ |
1213 | 0 | (void)_f; |
1214 | | |
1215 | | /* Set the VFL feature flags that this driver supports */ |
1216 | 0 | if (flags) { |
1217 | 0 | *flags = 0; |
1218 | 0 | *flags |= H5FD_FEAT_DATA_SIEVE; /* OK to perform data sieving for faster raw data reads & writes */ |
1219 | 0 | *flags |= H5FD_FEAT_AGGREGATE_SMALLDATA; /* OK to aggregate "small" raw data allocations */ |
1220 | 0 | *flags |= H5FD_FEAT_USE_ALLOC_SIZE; /* OK just pass the allocation size to the alloc callback */ |
1221 | 0 | *flags |= H5FD_FEAT_PAGED_AGGR; /* OK special file space mapping for paged aggregation */ |
1222 | 0 | } /* end if */ |
1223 | |
|
1224 | 0 | return (0); |
1225 | 0 | } /* end H5FD_multi_query() */ |
1226 | | |
1227 | | /*------------------------------------------------------------------------- |
1228 | | * Function: H5FD_multi_get_type_map |
1229 | | * |
1230 | | * Purpose: Retrieve the memory type mapping for this file |
1231 | | * |
1232 | | * Return: Success: non-negative |
1233 | | * Failure: negative |
1234 | | * |
1235 | | *------------------------------------------------------------------------- |
1236 | | */ |
1237 | | static herr_t |
1238 | | H5FD_multi_get_type_map(const H5FD_t *_file, H5FD_mem_t *type_map) |
1239 | 0 | { |
1240 | 0 | const H5FD_multi_t *file = (const H5FD_multi_t *)_file; |
1241 | | |
1242 | | /* Copy file's free space type mapping */ |
1243 | 0 | memcpy(type_map, file->fa.memb_map, sizeof(file->fa.memb_map)); |
1244 | |
|
1245 | 0 | return (0); |
1246 | 0 | } /* end H5FD_multi_get_type_map() */ |
1247 | | |
1248 | | /*------------------------------------------------------------------------- |
1249 | | * Function: H5FD_multi_get_eoa |
1250 | | * |
1251 | | * Purpose: Returns the end-of-address marker for the file. The EOA |
1252 | | * marker is the first address past the last byte allocated in |
1253 | | * the format address space. |
1254 | | * |
1255 | | * Return: Success: The end-of-address-marker |
1256 | | * |
1257 | | * Failure: HADDR_UNDEF |
1258 | | * |
1259 | | *------------------------------------------------------------------------- |
1260 | | */ |
1261 | | static haddr_t |
1262 | | H5FD_multi_get_eoa(const H5FD_t *_file, H5FD_mem_t type) |
1263 | 0 | { |
1264 | 0 | const H5FD_multi_t *file = (const H5FD_multi_t *)_file; |
1265 | 0 | haddr_t eoa = 0; |
1266 | | |
1267 | | /* Clear the error stack */ |
1268 | 0 | H5Eclear2(H5E_DEFAULT); |
1269 | | |
1270 | | /* The library used to have EOA for the whole file. But it's |
1271 | | * taken out because it makes little sense for MULTI files. |
1272 | | * However, the library sometimes queries it through H5F_get_eoa. |
1273 | | * Here the code finds the biggest EOA for individual file if |
1274 | | * the query is for TYPE == H5FD_MEM_DEFAULT. |
1275 | | */ |
1276 | 0 | if (H5FD_MEM_DEFAULT == type) { |
1277 | 0 | UNIQUE_MEMBERS (file->fa.memb_map, mt) { |
1278 | 0 | haddr_t memb_eoa; |
1279 | |
|
1280 | 0 | if (file->memb[mt]) { |
1281 | | /* Retrieve EOA */ |
1282 | 0 | H5E_BEGIN_TRY |
1283 | 0 | { |
1284 | 0 | memb_eoa = H5FDget_eoa(file->memb[mt], mt); |
1285 | 0 | } |
1286 | 0 | H5E_END_TRY |
1287 | |
|
1288 | 0 | if (HADDR_UNDEF == memb_eoa) |
1289 | 0 | H5Epush_ret(__func__, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, |
1290 | 0 | "member file has unknown eoa", HADDR_UNDEF); |
1291 | 0 | if (memb_eoa > 0) |
1292 | 0 | memb_eoa += file->fa.memb_addr[mt]; |
1293 | 0 | } |
1294 | 0 | else if (file->fa.relax) { |
1295 | | /* |
1296 | | * The member is not open yet (maybe it doesn't exist). Make the |
1297 | | * best guess about the end-of-file. |
1298 | | */ |
1299 | 0 | memb_eoa = file->memb_next[mt]; |
1300 | 0 | assert(HADDR_UNDEF != memb_eoa); |
1301 | 0 | } |
1302 | 0 | else { |
1303 | 0 | H5Epush_ret(__func__, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, "bad eoa", HADDR_UNDEF); |
1304 | 0 | } |
1305 | | |
1306 | 0 | if (memb_eoa > eoa) |
1307 | 0 | eoa = memb_eoa; |
1308 | 0 | } |
1309 | 0 | END_MEMBERS |
1310 | 0 | } |
1311 | 0 | else { |
1312 | 0 | H5FD_mem_t mmt = file->fa.memb_map[type]; |
1313 | |
|
1314 | 0 | if (H5FD_MEM_DEFAULT == mmt) |
1315 | 0 | mmt = type; |
1316 | |
|
1317 | 0 | if (file->memb[mmt]) { |
1318 | 0 | H5E_BEGIN_TRY |
1319 | 0 | { |
1320 | 0 | eoa = H5FDget_eoa(file->memb[mmt], mmt); |
1321 | 0 | } |
1322 | 0 | H5E_END_TRY |
1323 | |
|
1324 | 0 | if (HADDR_UNDEF == eoa) |
1325 | 0 | H5Epush_ret(__func__, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, "member file has unknown eoa", |
1326 | 0 | HADDR_UNDEF); |
1327 | 0 | if (eoa > 0) |
1328 | 0 | eoa += file->fa.memb_addr[mmt]; |
1329 | 0 | } |
1330 | 0 | else if (file->fa.relax) { |
1331 | | /* |
1332 | | * The member is not open yet (maybe it doesn't exist). Make the |
1333 | | * best guess about the end-of-file. |
1334 | | */ |
1335 | 0 | eoa = file->memb_next[mmt]; |
1336 | 0 | assert(HADDR_UNDEF != eoa); |
1337 | 0 | } |
1338 | 0 | else { |
1339 | 0 | H5Epush_ret(__func__, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, "bad eoa", HADDR_UNDEF); |
1340 | 0 | } |
1341 | 0 | } |
1342 | | |
1343 | 0 | return eoa; |
1344 | 0 | } /* end H5FD_multi_get_eoa() */ |
1345 | | |
1346 | | /*------------------------------------------------------------------------- |
1347 | | * Function: H5FD_multi_set_eoa |
1348 | | * |
1349 | | * Purpose: Set the end-of-address marker for the file by savig the new |
1350 | | * EOA value in the file struct. Also set the EOA marker for the |
1351 | | * subfile in which the new EOA value falls. We don't set the |
1352 | | * EOA values of any other subfiles. |
1353 | | * |
1354 | | * Return: Success: 0 |
1355 | | * |
1356 | | * Failure: -1 |
1357 | | * |
1358 | | *------------------------------------------------------------------------- |
1359 | | */ |
1360 | | static herr_t |
1361 | | H5FD_multi_set_eoa(H5FD_t *_file, H5FD_mem_t type, haddr_t eoa) |
1362 | 0 | { |
1363 | 0 | H5FD_multi_t *file = (H5FD_multi_t *)_file; |
1364 | 0 | H5FD_mem_t mmt; |
1365 | 0 | herr_t status; |
1366 | | |
1367 | | /* Clear the error stack */ |
1368 | 0 | H5Eclear2(H5E_DEFAULT); |
1369 | |
|
1370 | 0 | mmt = file->fa.memb_map[type]; |
1371 | 0 | if (H5FD_MEM_DEFAULT == mmt) { |
1372 | 0 | if (H5FD_MEM_DEFAULT == type) |
1373 | 0 | mmt = H5FD_MEM_SUPER; |
1374 | 0 | else |
1375 | 0 | mmt = type; |
1376 | 0 | } /* end if */ |
1377 | | |
1378 | | /* Handle backward compatibility in a quick and simple way. v1.6 library |
1379 | | * had EOA for the entire virtual file. But it wasn't meaningful. So v1.8 |
1380 | | * library doesn't have it anymore. It saves the EOA for the metadata file, |
1381 | | * instead. Here we try to figure out whether the EOA is from a v1.6 file |
1382 | | * by comparing its value. If it is a big value, we assume it's from v1.6 |
1383 | | * and simply discard it. This is the normal case when the metadata file |
1384 | | * has the smallest starting address. If the metadata file has the biggest |
1385 | | * address, the EOAs of v1.6 and v1.8 files are the same. It won't cause |
1386 | | * any trouble. (Please see Issue 2598 in Jira) SLU - 2011/6/21 |
1387 | | */ |
1388 | 0 | if (H5FD_MEM_SUPER == mmt && file->memb_eoa[H5FD_MEM_SUPER] > 0 && |
1389 | 0 | eoa > (file->memb_next[H5FD_MEM_SUPER] / 2)) |
1390 | 0 | return 0; |
1391 | | |
1392 | 0 | assert(eoa >= file->fa.memb_addr[mmt]); |
1393 | 0 | assert(eoa < file->memb_next[mmt]); |
1394 | |
|
1395 | 0 | H5E_BEGIN_TRY |
1396 | 0 | { |
1397 | 0 | status = H5FDset_eoa(file->memb[mmt], mmt, (eoa - file->fa.memb_addr[mmt])); |
1398 | 0 | } |
1399 | 0 | H5E_END_TRY |
1400 | 0 | if (status < 0) |
1401 | 0 | H5Epush_ret(__func__, H5E_ERR_CLS, H5E_FILE, H5E_BADVALUE, "member H5FDset_eoa failed", -1); |
1402 | | |
1403 | 0 | return 0; |
1404 | 0 | } /* end H5FD_multi_set_eoa() */ |
1405 | | |
1406 | | /*------------------------------------------------------------------------- |
1407 | | * Function: H5FD_multi_get_eof |
1408 | | * |
1409 | | * Purpose: Returns the end-of-file marker, which is the greater of |
1410 | | * either the total multi size or the current EOA marker. |
1411 | | * |
1412 | | * Return: Success: End of file address, the first address past |
1413 | | * the end of the multi of files or the current |
1414 | | * EOA, whichever is larger. |
1415 | | * |
1416 | | * Failure: HADDR_UNDEF |
1417 | | * |
1418 | | *------------------------------------------------------------------------- |
1419 | | */ |
1420 | | static haddr_t |
1421 | | H5FD_multi_get_eof(const H5FD_t *_file, H5FD_mem_t type) |
1422 | 0 | { |
1423 | 0 | const H5FD_multi_t *file = (const H5FD_multi_t *)_file; |
1424 | 0 | haddr_t eof = 0; |
1425 | | |
1426 | | /* Clear the error stack */ |
1427 | 0 | H5Eclear2(H5E_DEFAULT); |
1428 | |
|
1429 | 0 | if (H5FD_MEM_DEFAULT == type) { |
1430 | 0 | UNIQUE_MEMBERS (file->fa.memb_map, mt) { |
1431 | 0 | haddr_t tmp_eof; |
1432 | |
|
1433 | 0 | if (file->memb[mt]) { |
1434 | | /* Retrieve EOF */ |
1435 | 0 | H5E_BEGIN_TRY |
1436 | 0 | { |
1437 | 0 | tmp_eof = H5FDget_eof(file->memb[mt], type); |
1438 | 0 | } |
1439 | 0 | H5E_END_TRY |
1440 | |
|
1441 | 0 | if (HADDR_UNDEF == tmp_eof) |
1442 | 0 | H5Epush_ret(__func__, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, |
1443 | 0 | "member file has unknown eof", HADDR_UNDEF); |
1444 | 0 | if (tmp_eof > 0) |
1445 | 0 | tmp_eof += file->fa.memb_addr[mt]; |
1446 | 0 | } |
1447 | 0 | else if (file->fa.relax) { |
1448 | | /* |
1449 | | * The member is not open yet (maybe it doesn't exist). Make the |
1450 | | * best guess about the end-of-file. |
1451 | | */ |
1452 | 0 | tmp_eof = file->memb_next[mt]; |
1453 | 0 | assert(HADDR_UNDEF != tmp_eof); |
1454 | 0 | } |
1455 | 0 | else { |
1456 | 0 | H5Epush_ret(__func__, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, "bad eof", HADDR_UNDEF); |
1457 | 0 | } |
1458 | 0 | if (tmp_eof > eof) |
1459 | 0 | eof = tmp_eof; |
1460 | 0 | } |
1461 | 0 | END_MEMBERS |
1462 | 0 | } |
1463 | 0 | else { |
1464 | 0 | H5FD_mem_t mmt = file->fa.memb_map[type]; |
1465 | |
|
1466 | 0 | if (H5FD_MEM_DEFAULT == mmt) |
1467 | 0 | mmt = type; |
1468 | |
|
1469 | 0 | if (file->memb[mmt]) { |
1470 | | /* Retrieve EOF */ |
1471 | 0 | H5E_BEGIN_TRY |
1472 | 0 | { |
1473 | 0 | eof = H5FDget_eof(file->memb[mmt], mmt); |
1474 | 0 | } |
1475 | 0 | H5E_END_TRY |
1476 | |
|
1477 | 0 | if (HADDR_UNDEF == eof) |
1478 | 0 | H5Epush_ret(__func__, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, "member file has unknown eof", |
1479 | 0 | HADDR_UNDEF); |
1480 | 0 | if (eof > 0) |
1481 | 0 | eof += file->fa.memb_addr[mmt]; |
1482 | 0 | } |
1483 | 0 | else if (file->fa.relax) { |
1484 | | /* |
1485 | | * The member is not open yet (maybe it doesn't exist). Make the |
1486 | | * best guess about the end-of-file. |
1487 | | */ |
1488 | 0 | eof = file->memb_next[mmt]; |
1489 | 0 | assert(HADDR_UNDEF != eof); |
1490 | 0 | } |
1491 | 0 | else { |
1492 | 0 | H5Epush_ret(__func__, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, "bad eof", HADDR_UNDEF); |
1493 | 0 | } |
1494 | 0 | } |
1495 | 0 | return eof; |
1496 | 0 | } |
1497 | | |
1498 | | /*------------------------------------------------------------------------- |
1499 | | * Function: H5FD_multi_get_handle |
1500 | | * |
1501 | | * Purpose: Returns the file handle of MULTI file driver. |
1502 | | * |
1503 | | * Returns: Non-negative if succeed or negative if fails. |
1504 | | * |
1505 | | *------------------------------------------------------------------------- |
1506 | | */ |
1507 | | static herr_t |
1508 | | H5FD_multi_get_handle(H5FD_t *_file, hid_t fapl, void **file_handle) |
1509 | 0 | { |
1510 | 0 | H5FD_multi_t *file = (H5FD_multi_t *)_file; |
1511 | 0 | H5FD_mem_t type, mmt; |
1512 | | |
1513 | | /* Get data type for multi driver */ |
1514 | 0 | if (H5Pget_multi_type(fapl, &type) < 0) |
1515 | 0 | H5Epush_ret(__func__, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, "can't get data type for multi driver", |
1516 | 0 | -1); |
1517 | 0 | if (type < H5FD_MEM_DEFAULT || type >= H5FD_MEM_NTYPES) |
1518 | 0 | H5Epush_ret(__func__, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, "data type is out of range", -1); |
1519 | 0 | mmt = file->fa.memb_map[type]; |
1520 | 0 | if (H5FD_MEM_DEFAULT == mmt) |
1521 | 0 | mmt = type; |
1522 | |
|
1523 | 0 | return (H5FDget_vfd_handle(file->memb[mmt], fapl, file_handle)); |
1524 | 0 | } |
1525 | | |
1526 | | /*------------------------------------------------------------------------- |
1527 | | * Function: H5FD_multi_alloc |
1528 | | * |
1529 | | * Purpose: Allocate file memory. |
1530 | | * |
1531 | | * Return: Success: Address of new memory |
1532 | | * |
1533 | | * Failure: HADDR_UNDEF |
1534 | | * |
1535 | | *------------------------------------------------------------------------- |
1536 | | */ |
1537 | | static haddr_t |
1538 | | H5FD_multi_alloc(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, hsize_t size) |
1539 | 0 | { |
1540 | 0 | H5FD_multi_t *file = (H5FD_multi_t *)_file; |
1541 | 0 | H5FD_mem_t mmt; |
1542 | 0 | haddr_t addr; |
1543 | |
|
1544 | 0 | mmt = file->fa.memb_map[type]; |
1545 | 0 | if (H5FD_MEM_DEFAULT == mmt) |
1546 | 0 | mmt = type; |
1547 | | |
1548 | | /* XXX: NEED to work on this again */ |
1549 | 0 | if (file->pub.paged_aggr) { |
1550 | 0 | ALL_MEMBERS (mt) { |
1551 | 0 | if (file->memb[mt]) |
1552 | 0 | file->memb[mt]->paged_aggr = file->pub.paged_aggr; |
1553 | 0 | } |
1554 | 0 | END_MEMBERS |
1555 | 0 | } |
1556 | |
|
1557 | 0 | if (HADDR_UNDEF == (addr = H5FDalloc(file->memb[mmt], mmt, dxpl_id, size))) |
1558 | 0 | H5Epush_ret(__func__, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, "member file can't alloc", |
1559 | 0 | HADDR_UNDEF); |
1560 | 0 | addr += file->fa.memb_addr[mmt]; |
1561 | |
|
1562 | 0 | return addr; |
1563 | 0 | } |
1564 | | |
1565 | | /*------------------------------------------------------------------------- |
1566 | | * Function: H5FD_multi_free |
1567 | | * |
1568 | | * Purpose: Frees memory |
1569 | | * |
1570 | | * Return: Success: 0 |
1571 | | * |
1572 | | * Failure: -1 |
1573 | | * |
1574 | | *------------------------------------------------------------------------- |
1575 | | */ |
1576 | | static herr_t |
1577 | | H5FD_multi_free(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, hsize_t size) |
1578 | 0 | { |
1579 | 0 | H5FD_multi_t *file = (H5FD_multi_t *)_file; |
1580 | 0 | H5FD_mem_t mmt; |
1581 | | |
1582 | | /* Clear the error stack */ |
1583 | 0 | H5Eclear2(H5E_DEFAULT); |
1584 | |
|
1585 | 0 | mmt = file->fa.memb_map[type]; |
1586 | 0 | if (H5FD_MEM_DEFAULT == mmt) |
1587 | 0 | mmt = type; |
1588 | |
|
1589 | 0 | assert(addr >= file->fa.memb_addr[mmt]); |
1590 | 0 | assert(addr + size <= file->memb_next[mmt]); |
1591 | 0 | return H5FDfree(file->memb[mmt], mmt, dxpl_id, addr - file->fa.memb_addr[mmt], size); |
1592 | 0 | } |
1593 | | |
1594 | | /*------------------------------------------------------------------------- |
1595 | | * Function: H5FD_multi_read |
1596 | | * |
1597 | | * Purpose: Reads SIZE bytes of data from FILE beginning at address ADDR |
1598 | | * into buffer BUF according to data transfer properties in |
1599 | | * DXPL_ID. |
1600 | | * |
1601 | | * Return: Success: Zero. Result is stored in caller-supplied |
1602 | | * buffer BUF. |
1603 | | * |
1604 | | * Failure: -1, contents of buffer BUF are undefined. |
1605 | | * |
1606 | | *------------------------------------------------------------------------- |
1607 | | */ |
1608 | | static herr_t |
1609 | | H5FD_multi_read(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, size_t size, void *_buf /*out*/) |
1610 | 0 | { |
1611 | 0 | H5FD_multi_t *file = (H5FD_multi_t *)_file; |
1612 | 0 | H5FD_mem_t mt, mmt, hi = H5FD_MEM_DEFAULT; |
1613 | 0 | haddr_t start_addr = 0; |
1614 | | |
1615 | | /* Clear the error stack */ |
1616 | 0 | H5Eclear2(H5E_DEFAULT); |
1617 | | |
1618 | | /* Find the file to which this address belongs */ |
1619 | 0 | for (mt = H5FD_MEM_SUPER; mt < H5FD_MEM_NTYPES; mt = (H5FD_mem_t)(mt + 1)) { |
1620 | 0 | mmt = file->fa.memb_map[mt]; |
1621 | 0 | if (H5FD_MEM_DEFAULT == mmt) |
1622 | 0 | mmt = mt; |
1623 | 0 | assert(mmt > 0 && mmt < H5FD_MEM_NTYPES); |
1624 | |
|
1625 | 0 | if (file->fa.memb_addr[mmt] > addr) |
1626 | 0 | continue; |
1627 | 0 | if (file->fa.memb_addr[mmt] >= start_addr) { |
1628 | 0 | start_addr = file->fa.memb_addr[mmt]; |
1629 | 0 | hi = mmt; |
1630 | 0 | } /* end if */ |
1631 | 0 | } /* end for */ |
1632 | 0 | assert(hi > 0); |
1633 | | |
1634 | | /* Read from that member */ |
1635 | 0 | return H5FDread(file->memb[hi], type, dxpl_id, addr - start_addr, size, _buf); |
1636 | 0 | } /* end H5FD_multi_read() */ |
1637 | | |
1638 | | /*------------------------------------------------------------------------- |
1639 | | * Function: H5FD_multi_write |
1640 | | * |
1641 | | * Purpose: Writes SIZE bytes of data to FILE beginning at address ADDR |
1642 | | * from buffer BUF according to data transfer properties in |
1643 | | * DXPL_ID. |
1644 | | * |
1645 | | * Return: Success: Zero |
1646 | | * |
1647 | | * Failure: -1 |
1648 | | * |
1649 | | *------------------------------------------------------------------------- |
1650 | | */ |
1651 | | static herr_t |
1652 | | H5FD_multi_write(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, size_t size, const void *_buf) |
1653 | 0 | { |
1654 | 0 | H5FD_multi_t *file = (H5FD_multi_t *)_file; |
1655 | 0 | H5FD_mem_t mt, mmt, hi = H5FD_MEM_DEFAULT; |
1656 | 0 | haddr_t start_addr = 0; |
1657 | | |
1658 | | /* Clear the error stack */ |
1659 | 0 | H5Eclear2(H5E_DEFAULT); |
1660 | | |
1661 | | /* Find the file to which this address belongs */ |
1662 | 0 | for (mt = H5FD_MEM_SUPER; mt < H5FD_MEM_NTYPES; mt = (H5FD_mem_t)(mt + 1)) { |
1663 | 0 | mmt = file->fa.memb_map[mt]; |
1664 | 0 | if (H5FD_MEM_DEFAULT == mmt) |
1665 | 0 | mmt = mt; |
1666 | 0 | assert(mmt > 0 && mmt < H5FD_MEM_NTYPES); |
1667 | |
|
1668 | 0 | if (file->fa.memb_addr[mmt] > addr) |
1669 | 0 | continue; |
1670 | 0 | if (file->fa.memb_addr[mmt] >= start_addr) { |
1671 | 0 | start_addr = file->fa.memb_addr[mmt]; |
1672 | 0 | hi = mmt; |
1673 | 0 | } /* end if */ |
1674 | 0 | } /* end for */ |
1675 | 0 | assert(hi > 0); |
1676 | | |
1677 | | /* Write to that member */ |
1678 | 0 | return H5FDwrite(file->memb[hi], type, dxpl_id, addr - start_addr, size, _buf); |
1679 | 0 | } /* end H5FD_multi_write() */ |
1680 | | |
1681 | | /*------------------------------------------------------------------------- |
1682 | | * Function: H5FD_multi_flush |
1683 | | * |
1684 | | * Purpose: Flushes all multi members. |
1685 | | * |
1686 | | * Return: Success: 0 |
1687 | | * |
1688 | | * Failure: -1, as many files flushed as possible. |
1689 | | * |
1690 | | *------------------------------------------------------------------------- |
1691 | | */ |
1692 | | static herr_t |
1693 | | H5FD_multi_flush(H5FD_t *_file, hid_t dxpl_id, bool closing) |
1694 | 0 | { |
1695 | 0 | H5FD_multi_t *file = (H5FD_multi_t *)_file; |
1696 | 0 | H5FD_mem_t mt; |
1697 | 0 | int nerrors = 0; |
1698 | | |
1699 | | /* Clear the error stack */ |
1700 | 0 | H5Eclear2(H5E_DEFAULT); |
1701 | | |
1702 | | /* Flush each file */ |
1703 | 0 | for (mt = H5FD_MEM_SUPER; mt < H5FD_MEM_NTYPES; mt = (H5FD_mem_t)(mt + 1)) { |
1704 | 0 | if (file->memb[mt]) { |
1705 | 0 | H5E_BEGIN_TRY |
1706 | 0 | { |
1707 | 0 | if (H5FDflush(file->memb[mt], dxpl_id, closing) < 0) |
1708 | 0 | nerrors++; |
1709 | 0 | } |
1710 | 0 | H5E_END_TRY |
1711 | 0 | } |
1712 | 0 | } |
1713 | 0 | if (nerrors) |
1714 | 0 | H5Epush_ret(__func__, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, "error flushing member files", -1); |
1715 | | |
1716 | 0 | return 0; |
1717 | 0 | } |
1718 | | |
1719 | | /*------------------------------------------------------------------------- |
1720 | | * Function: H5FD_multi_truncate |
1721 | | * |
1722 | | * Purpose: Truncates all multi members. |
1723 | | * |
1724 | | * Return: Success: 0 |
1725 | | * Failure: -1, as many files truncated as possible. |
1726 | | * |
1727 | | *------------------------------------------------------------------------- |
1728 | | */ |
1729 | | static herr_t |
1730 | | H5FD_multi_truncate(H5FD_t *_file, hid_t dxpl_id, bool closing) |
1731 | 0 | { |
1732 | 0 | H5FD_multi_t *file = (H5FD_multi_t *)_file; |
1733 | 0 | H5FD_mem_t mt; |
1734 | 0 | int nerrors = 0; |
1735 | | |
1736 | | /* Clear the error stack */ |
1737 | 0 | H5Eclear2(H5E_DEFAULT); |
1738 | | |
1739 | | /* Truncate each file */ |
1740 | 0 | for (mt = H5FD_MEM_SUPER; mt < H5FD_MEM_NTYPES; mt = (H5FD_mem_t)(mt + 1)) { |
1741 | 0 | if (file->memb[mt]) { |
1742 | 0 | H5E_BEGIN_TRY |
1743 | 0 | { |
1744 | 0 | if (H5FDtruncate(file->memb[mt], dxpl_id, closing) < 0) |
1745 | 0 | nerrors++; |
1746 | 0 | } |
1747 | 0 | H5E_END_TRY |
1748 | 0 | } |
1749 | 0 | } |
1750 | 0 | if (nerrors) |
1751 | 0 | H5Epush_ret(__func__, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, "error truncating member files", -1); |
1752 | | |
1753 | 0 | return 0; |
1754 | 0 | } /* end H5FD_multi_truncate() */ |
1755 | | |
1756 | | /*------------------------------------------------------------------------- |
1757 | | * Function: H5FD_multi_lock |
1758 | | * |
1759 | | * Purpose: Place a lock on all multi members. |
1760 | | * When there is error in locking a member file, it will not |
1761 | | * proceed further and will try to remove the locks of those |
1762 | | * member files that are locked before error is encountered. |
1763 | | * |
1764 | | * Return: Success: 0 |
1765 | | * Failure: -1 |
1766 | | * |
1767 | | *------------------------------------------------------------------------- |
1768 | | */ |
1769 | | static herr_t |
1770 | | H5FD_multi_lock(H5FD_t *_file, bool rw) |
1771 | 0 | { |
1772 | 0 | H5FD_multi_t *file = (H5FD_multi_t *)_file; |
1773 | 0 | int nerrors = 0; |
1774 | 0 | H5FD_mem_t out_mt = H5FD_MEM_DEFAULT; |
1775 | | |
1776 | | /* Clear the error stack */ |
1777 | 0 | H5Eclear2(H5E_DEFAULT); |
1778 | | |
1779 | | /* Lock all member files */ |
1780 | 0 | ALL_MEMBERS (mt) { |
1781 | 0 | out_mt = mt; |
1782 | 0 | if (file->memb[mt]) { |
1783 | 0 | H5E_BEGIN_TRY |
1784 | 0 | { |
1785 | 0 | if (H5FDlock(file->memb[mt], rw) < 0) { |
1786 | 0 | nerrors++; |
1787 | 0 | break; |
1788 | 0 | } /* end if */ |
1789 | 0 | } |
1790 | 0 | H5E_END_TRY |
1791 | 0 | } /* end if */ |
1792 | 0 | } |
1793 | 0 | END_MEMBERS |
1794 | | |
1795 | | /* Try to unlock the member files that are locked before error is encountered */ |
1796 | 0 | if (nerrors) { |
1797 | 0 | H5FD_mem_t k; |
1798 | |
|
1799 | 0 | for (k = H5FD_MEM_DEFAULT; k < out_mt; k = (H5FD_mem_t)(k + 1)) { |
1800 | 0 | H5E_BEGIN_TRY |
1801 | 0 | { |
1802 | 0 | if (H5FDunlock(file->memb[k]) < 0) |
1803 | 0 | nerrors++; |
1804 | 0 | } |
1805 | 0 | H5E_END_TRY |
1806 | 0 | } /* end for */ |
1807 | 0 | } /* end if */ |
1808 | |
|
1809 | 0 | if (nerrors) |
1810 | 0 | H5Epush_ret(__func__, H5E_ERR_CLS, H5E_VFL, H5E_CANTLOCKFILE, "error locking member files", -1); |
1811 | 0 | return 0; |
1812 | |
|
1813 | 0 | } /* H5FD_multi_lock() */ |
1814 | | |
1815 | | /*------------------------------------------------------------------------- |
1816 | | * Function: H5FD_multi_unlock |
1817 | | * |
1818 | | * Purpose: Remove the lock on all multi members. |
1819 | | * It will try to unlock all member files but will record error |
1820 | | * encountered. |
1821 | | * |
1822 | | * Return: Success: 0 |
1823 | | * Failure: -1 |
1824 | | * |
1825 | | *------------------------------------------------------------------------- |
1826 | | */ |
1827 | | static herr_t |
1828 | | H5FD_multi_unlock(H5FD_t *_file) |
1829 | 0 | { |
1830 | 0 | H5FD_multi_t *file = (H5FD_multi_t *)_file; |
1831 | 0 | int nerrors = 0; |
1832 | | |
1833 | | /* Clear the error stack */ |
1834 | 0 | H5Eclear2(H5E_DEFAULT); |
1835 | |
|
1836 | 0 | ALL_MEMBERS (mt) { |
1837 | 0 | if (file->memb[mt]) |
1838 | 0 | if (H5FDunlock(file->memb[mt]) < 0) |
1839 | 0 | nerrors++; |
1840 | 0 | } |
1841 | 0 | END_MEMBERS |
1842 | |
|
1843 | 0 | if (nerrors) |
1844 | 0 | H5Epush_ret(__func__, H5E_ERR_CLS, H5E_VFL, H5E_CANTUNLOCKFILE, "error unlocking member files", -1); |
1845 | | |
1846 | 0 | return 0; |
1847 | 0 | } /* H5FD_multi_unlock() */ |
1848 | | |
1849 | | /*------------------------------------------------------------------------- |
1850 | | * Function: compute_next |
1851 | | * |
1852 | | * Purpose: Compute the memb_next[] values of the file based on the |
1853 | | * file's member map and the member starting addresses. |
1854 | | * |
1855 | | * Return: Success: 0 |
1856 | | * |
1857 | | * Failure: -1 |
1858 | | * |
1859 | | *------------------------------------------------------------------------- |
1860 | | */ |
1861 | | static int |
1862 | | compute_next(H5FD_multi_t *file) |
1863 | 0 | { |
1864 | | /* Clear the error stack */ |
1865 | 0 | H5Eclear2(H5E_DEFAULT); |
1866 | |
|
1867 | 0 | ALL_MEMBERS (mt) { |
1868 | 0 | file->memb_next[mt] = HADDR_UNDEF; |
1869 | 0 | } |
1870 | 0 | END_MEMBERS |
1871 | |
|
1872 | 0 | UNIQUE_MEMBERS (file->fa.memb_map, mt1) { |
1873 | 0 | UNIQUE_MEMBERS2(file->fa.memb_map, mt2) |
1874 | 0 | { |
1875 | 0 | if (file->fa.memb_addr[mt1] < file->fa.memb_addr[mt2] && |
1876 | 0 | (HADDR_UNDEF == file->memb_next[mt1] || file->memb_next[mt1] > file->fa.memb_addr[mt2])) { |
1877 | 0 | file->memb_next[mt1] = file->fa.memb_addr[mt2]; |
1878 | 0 | } |
1879 | 0 | } |
1880 | 0 | END_MEMBERS |
1881 | 0 | if (HADDR_UNDEF == file->memb_next[mt1]) { |
1882 | 0 | file->memb_next[mt1] = HADDR_MAX; /*last member*/ |
1883 | 0 | } |
1884 | 0 | } |
1885 | 0 | END_MEMBERS |
1886 | |
|
1887 | 0 | return 0; |
1888 | 0 | } |
1889 | | |
1890 | | /*------------------------------------------------------------------------- |
1891 | | * Function: open_members |
1892 | | * |
1893 | | * Purpose: Opens all members which are not opened yet. |
1894 | | * |
1895 | | * Return: Success: 0 |
1896 | | * |
1897 | | * Failure: -1 |
1898 | | * |
1899 | | *------------------------------------------------------------------------- |
1900 | | */ |
1901 | | static int |
1902 | | open_members(H5FD_multi_t *file) |
1903 | 0 | { |
1904 | 0 | char tmp[H5FD_MULT_MAX_FILE_NAME_LEN]; |
1905 | 0 | int nerrors = 0; |
1906 | 0 | int nchars; |
1907 | | |
1908 | | /* Clear the error stack */ |
1909 | 0 | H5Eclear2(H5E_DEFAULT); |
1910 | |
|
1911 | 0 | UNIQUE_MEMBERS (file->fa.memb_map, mt) { |
1912 | 0 | if (file->memb[mt]) |
1913 | 0 | continue; /*already open*/ |
1914 | 0 | assert(file->fa.memb_name[mt]); |
1915 | |
|
1916 | 0 | H5_WARN_FORMAT_NONLITERAL_OFF |
1917 | 0 | nchars = snprintf(tmp, sizeof(tmp), file->fa.memb_name[mt], file->name); |
1918 | 0 | H5_WARN_FORMAT_NONLITERAL_ON |
1919 | 0 | if (nchars < 0 || nchars >= (int)sizeof(tmp)) |
1920 | 0 | H5Epush_ret(__func__, H5E_ERR_CLS, H5E_VFL, H5E_BADVALUE, |
1921 | 0 | "filename is too long and would be truncated", -1); |
1922 | | |
1923 | 0 | H5E_BEGIN_TRY |
1924 | 0 | { |
1925 | 0 | file->memb[mt] = H5FDopen(tmp, file->flags, file->fa.memb_fapl[mt], HADDR_UNDEF); |
1926 | 0 | } |
1927 | 0 | H5E_END_TRY |
1928 | 0 | if (!file->memb[mt]) { |
1929 | 0 | if (!file->fa.relax || (file->flags & H5F_ACC_RDWR)) |
1930 | 0 | nerrors++; |
1931 | 0 | } |
1932 | 0 | } |
1933 | 0 | END_MEMBERS |
1934 | 0 | if (nerrors) |
1935 | 0 | H5Epush_ret(__func__, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, "error opening member files", -1); |
1936 | | |
1937 | 0 | return 0; |
1938 | 0 | } |
1939 | | |
1940 | | /*------------------------------------------------------------------------- |
1941 | | * Function: H5FD_multi_delete |
1942 | | * |
1943 | | * Purpose: Delete a file |
1944 | | * |
1945 | | * Return: SUCCEED/FAIL |
1946 | | * |
1947 | | *------------------------------------------------------------------------- |
1948 | | */ |
1949 | | static herr_t |
1950 | | H5FD_multi_delete(const char *filename, hid_t fapl_id) |
1951 | 0 | { |
1952 | 0 | char full_filename[H5FD_MULT_MAX_FILE_NAME_LEN]; |
1953 | 0 | int nchars; |
1954 | 0 | const H5FD_multi_fapl_t *fa; |
1955 | 0 | H5FD_multi_fapl_t default_fa; |
1956 | | |
1957 | | /* Clear the error stack */ |
1958 | 0 | H5Eclear2(H5E_DEFAULT); |
1959 | |
|
1960 | 0 | assert(filename); |
1961 | | |
1962 | | /* Get the driver info */ |
1963 | 0 | H5E_BEGIN_TRY |
1964 | 0 | { |
1965 | 0 | fa = (const H5FD_multi_fapl_t *)H5Pget_driver_info(fapl_id); |
1966 | 0 | } |
1967 | 0 | H5E_END_TRY |
1968 | 0 | if (!fa) { |
1969 | 0 | char *env = getenv(HDF5_DRIVER); |
1970 | |
|
1971 | 0 | if (env && !strcmp(env, "split")) { |
1972 | 0 | if (H5FD_split_populate_config(NULL, H5P_DEFAULT, NULL, H5P_DEFAULT, true, &default_fa) < 0) |
1973 | 0 | H5Epush_ret(__func__, H5E_ERR_CLS, H5E_VFL, H5E_CANTSET, "can't setup driver configuration", |
1974 | 0 | -1); |
1975 | 0 | } |
1976 | 0 | else { |
1977 | 0 | if (H5FD_multi_populate_config(NULL, NULL, NULL, NULL, true, &default_fa) < 0) |
1978 | 0 | H5Epush_ret(__func__, H5E_ERR_CLS, H5E_VFL, H5E_CANTSET, "can't setup driver configuration", |
1979 | 0 | -1); |
1980 | 0 | } |
1981 | | |
1982 | 0 | fa = &default_fa; |
1983 | 0 | } |
1984 | 0 | assert(fa); |
1985 | | |
1986 | | /* Delete each member file using the underlying fapl */ |
1987 | 0 | UNIQUE_MEMBERS (fa->memb_map, mt) { |
1988 | 0 | assert(fa->memb_name[mt]); |
1989 | 0 | assert(fa->memb_fapl[mt] >= 0); |
1990 | |
|
1991 | 0 | H5_WARN_FORMAT_NONLITERAL_OFF |
1992 | 0 | nchars = snprintf(full_filename, sizeof(full_filename), fa->memb_name[mt], filename); |
1993 | 0 | H5_WARN_FORMAT_NONLITERAL_ON |
1994 | 0 | if (nchars < 0 || nchars >= (int)sizeof(full_filename)) |
1995 | 0 | H5Epush_ret(__func__, H5E_ERR_CLS, H5E_VFL, H5E_BADVALUE, |
1996 | 0 | "filename is too long and would be truncated", -1); |
1997 | | |
1998 | 0 | if (H5FDdelete(full_filename, fa->memb_fapl[mt]) < 0) |
1999 | 0 | H5Epush_ret(__func__, H5E_ERR_CLS, H5E_VFL, H5E_BADVALUE, "error deleting member files", -1); |
2000 | 0 | } |
2001 | 0 | END_MEMBERS |
2002 | | |
2003 | 0 | return 0; |
2004 | 0 | } /* end H5FD_multi_delete() */ |
2005 | | |
2006 | | /*------------------------------------------------------------------------- |
2007 | | * Function: H5FD_multi_ctl |
2008 | | * |
2009 | | * Purpose: Multi VFD version of the ctl callback. |
2010 | | * |
2011 | | * The desired operation is specified by the op_code |
2012 | | * parameter. |
2013 | | * |
2014 | | * The flags parameter controls management of op_codes that |
2015 | | * are unknown to the callback |
2016 | | * |
2017 | | * The input and output parameters allow op_code specific |
2018 | | * input and output |
2019 | | * |
2020 | | * At present, this VFD supports no op codes of its own. |
2021 | | * |
2022 | | * Return: Non-negative on success/Negative on failure |
2023 | | * |
2024 | | *------------------------------------------------------------------------- |
2025 | | */ |
2026 | | static herr_t |
2027 | | H5FD_multi_ctl(H5FD_t *_file, uint64_t op_code, uint64_t flags, const void *input, void **output) |
2028 | 0 | { |
2029 | 0 | H5FD_multi_t *file = (H5FD_multi_t *)_file; |
2030 | 0 | herr_t ret_value = 0; |
2031 | | |
2032 | | /* Silence compiler */ |
2033 | 0 | (void)file; |
2034 | 0 | (void)input; |
2035 | 0 | (void)output; |
2036 | | |
2037 | | /* Clear the error stack */ |
2038 | 0 | H5Eclear2(H5E_DEFAULT); |
2039 | |
|
2040 | 0 | switch (op_code) { |
2041 | | /* Unknown op code */ |
2042 | 0 | default: |
2043 | 0 | if (flags & H5FD_CTL_FAIL_IF_UNKNOWN_FLAG) |
2044 | 0 | H5Epush_ret(__func__, H5E_ERR_CLS, H5E_VFL, H5E_FCNTL, |
2045 | 0 | "VFD ctl request failed (unknown op code and fail if unknown flag is set)", -1); |
2046 | | |
2047 | 0 | break; |
2048 | 0 | } |
2049 | | |
2050 | 0 | return ret_value; |
2051 | 0 | } /* end H5FD_multi_ctl() */ |
2052 | | |
2053 | | #ifdef H5private_H |
2054 | | /* |
2055 | | * This is not related to the functionality of the driver code. |
2056 | | * It is added here to trigger warning if HDF5 private definitions are included |
2057 | | * by mistake. The code should use only HDF5 public API and definitions. |
2058 | | */ |
2059 | | #error "Do not use HDF5 private definitions" |
2060 | | #endif |