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