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