#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include "hdf5.h"
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE 1
#endif
#define UNIQUE_MEMBERS_CORE(MAP, ITER, SEEN, LOOPVAR) { \
H5FD_mem_t ITER, LOOPVAR; \
unsigned SEEN[H5FD_MEM_NTYPES]; \
\
memset(SEEN, 0, sizeof SEEN); \
for (ITER=H5FD_MEM_SUPER; ITER<H5FD_MEM_NTYPES; ITER=(H5FD_mem_t)(ITER+1)) { \
LOOPVAR = MAP[ITER]; \
if (H5FD_MEM_DEFAULT==LOOPVAR) LOOPVAR=ITER; \
assert(LOOPVAR>0 && LOOPVAR<H5FD_MEM_NTYPES); \
if (SEEN[LOOPVAR]++) continue; \
#define UNIQUE_MEMBERS(MAP, LOOPVAR) \
UNIQUE_MEMBERS_CORE(MAP, _unmapped, _seen, LOOPVAR)
#define UNIQUE_MEMBERS2(MAP, LOOPVAR) \
UNIQUE_MEMBERS_CORE(MAP, _unmapped2, _seen2, LOOPVAR)
#define ALL_MEMBERS(LOOPVAR) { \
H5FD_mem_t LOOPVAR; \
for (LOOPVAR=H5FD_MEM_DEFAULT; LOOPVAR<H5FD_MEM_NTYPES; LOOPVAR=(H5FD_mem_t)(LOOPVAR+1)) {
#define END_MEMBERS }}
#define H5FD_MULT_MAX_FILE_NAME_LEN 1024
static hid_t H5FD_MULTI_g = 0;
typedef struct H5FD_multi_fapl_t {
H5FD_mem_t memb_map[H5FD_MEM_NTYPES];
hid_t memb_fapl[H5FD_MEM_NTYPES];
char *memb_name[H5FD_MEM_NTYPES];
haddr_t memb_addr[H5FD_MEM_NTYPES];
hbool_t relax;
} H5FD_multi_fapl_t;
typedef struct H5FD_multi_t {
H5FD_t pub;
H5FD_multi_fapl_t fa;
haddr_t memb_next[H5FD_MEM_NTYPES];
H5FD_t *memb[H5FD_MEM_NTYPES];
haddr_t memb_eoa[H5FD_MEM_NTYPES];
unsigned flags;
char *name;
} H5FD_multi_t;
typedef struct H5FD_multi_dxpl_t {
hid_t memb_dxpl[H5FD_MEM_NTYPES];
} H5FD_multi_dxpl_t;
static char *my_strdup(const char *s);
static int compute_next(H5FD_multi_t *file);
static int open_members(H5FD_multi_t *file);
static herr_t H5FD_multi_term(void);
static hsize_t H5FD_multi_sb_size(H5FD_t *file);
static herr_t H5FD_multi_sb_encode(H5FD_t *file, char *name,
unsigned char *buf);
static herr_t H5FD_multi_sb_decode(H5FD_t *file, const char *name,
const unsigned char *buf);
static void *H5FD_multi_fapl_get(H5FD_t *file);
static void *H5FD_multi_fapl_copy(const void *_old_fa);
static herr_t H5FD_multi_fapl_free(void *_fa);
static H5FD_t *H5FD_multi_open(const char *name, unsigned flags,
hid_t fapl_id, haddr_t maxaddr);
static herr_t H5FD_multi_close(H5FD_t *_file);
static int H5FD_multi_cmp(const H5FD_t *_f1, const H5FD_t *_f2);
static herr_t H5FD_multi_query(const H5FD_t *_f1, unsigned long *flags);
static herr_t H5FD_multi_get_type_map(const H5FD_t *file, H5FD_mem_t *type_map);
static haddr_t H5FD_multi_get_eoa(const H5FD_t *_file, H5FD_mem_t type);
static herr_t H5FD_multi_set_eoa(H5FD_t *_file, H5FD_mem_t type, haddr_t eoa);
static haddr_t H5FD_multi_get_eof(const H5FD_t *_file, H5FD_mem_t type);
static herr_t H5FD_multi_get_handle(H5FD_t *_file, hid_t fapl, void** file_handle);
static haddr_t H5FD_multi_alloc(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, hsize_t size);
static herr_t H5FD_multi_free(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr,
hsize_t size);
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);
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);
static herr_t H5FD_multi_flush(H5FD_t *_file, hid_t dxpl_id, hbool_t closing);
static herr_t H5FD_multi_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing);
static herr_t H5FD_multi_lock(H5FD_t *_file, hbool_t rw);
static herr_t H5FD_multi_unlock(H5FD_t *_file);
static const H5FD_class_t H5FD_multi_g = {
"multi",
HADDR_MAX,
H5F_CLOSE_WEAK,
H5FD_multi_term,
H5FD_multi_sb_size,
H5FD_multi_sb_encode,
H5FD_multi_sb_decode,
sizeof(H5FD_multi_fapl_t),
H5FD_multi_fapl_get,
H5FD_multi_fapl_copy,
H5FD_multi_fapl_free,
0,
NULL,
NULL,
H5FD_multi_open,
H5FD_multi_close,
H5FD_multi_cmp,
H5FD_multi_query,
H5FD_multi_get_type_map,
H5FD_multi_alloc,
H5FD_multi_free,
H5FD_multi_get_eoa,
H5FD_multi_set_eoa,
H5FD_multi_get_eof,
H5FD_multi_get_handle,
H5FD_multi_read,
H5FD_multi_write,
H5FD_multi_flush,
H5FD_multi_truncate,
H5FD_multi_lock,
H5FD_multi_unlock,
H5FD_FLMAP_DEFAULT
};
static char *
my_strdup(const char *s)
{
char *x;
size_t str_len;
if(!s)
return NULL;
str_len = strlen(s) + 1;
if(NULL == (x = (char *)malloc(str_len)))
return NULL;
memcpy(x, s, str_len);
return x;
}
hid_t
H5FD_multi_init(void)
{
H5Eclear2(H5E_DEFAULT);
if(H5I_VFL != H5Iget_type(H5FD_MULTI_g))
H5FD_MULTI_g = H5FDregister(&H5FD_multi_g);
return H5FD_MULTI_g;
}
static herr_t
H5FD_multi_term(void)
{
H5FD_MULTI_g=0;
return 0;
}
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)
{
H5FD_mem_t memb_map[H5FD_MEM_NTYPES];
hid_t memb_fapl[H5FD_MEM_NTYPES];
const char *memb_name[H5FD_MEM_NTYPES];
char meta_name[H5FD_MULT_MAX_FILE_NAME_LEN];
char raw_name[H5FD_MULT_MAX_FILE_NAME_LEN];
haddr_t memb_addr[H5FD_MEM_NTYPES];
H5Eclear2(H5E_DEFAULT);
ALL_MEMBERS(mt) {
memb_map[mt] = ((mt == H5FD_MEM_DRAW || mt == H5FD_MEM_GHEAP) ? H5FD_MEM_DRAW : H5FD_MEM_SUPER);
memb_fapl[mt] = -1;
memb_name[mt] = NULL;
memb_addr[mt] = HADDR_UNDEF;
} END_MEMBERS;
memb_fapl[H5FD_MEM_SUPER] = meta_plist_id;
memb_fapl[H5FD_MEM_DRAW] = raw_plist_id;
if(meta_ext) {
if(strstr(meta_ext, "%s")) {
strncpy(meta_name, meta_ext, sizeof(meta_name));
meta_name[sizeof(meta_name) - 1] = '\0';
}
else
sprintf(meta_name, "%%s%s", meta_ext);
}
else {
strncpy(meta_name, "%s.meta", sizeof(meta_name));
meta_name[sizeof(meta_name) - 1] = '\0';
}
memb_name[H5FD_MEM_SUPER] = meta_name;
if(raw_ext) {
if(strstr(raw_ext, "%s")) {
strncpy(raw_name, raw_ext, sizeof(raw_name));
raw_name[sizeof(raw_name) - 1] = '\0';
}
else
sprintf(raw_name, "%%s%s", raw_ext);
}
else {
strncpy(raw_name, "%s.raw", sizeof(raw_name));
raw_name[sizeof(raw_name) - 1] = '\0';
}
memb_name[H5FD_MEM_DRAW] = raw_name;
memb_addr[H5FD_MEM_SUPER] = 0;
memb_addr[H5FD_MEM_DRAW] = HADDR_MAX/2;
return H5Pset_fapl_multi(fapl, memb_map, memb_fapl, memb_name, memb_addr, TRUE);
}
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)
{
H5FD_multi_fapl_t fa;
H5FD_mem_t mt, mmt;
H5FD_mem_t _memb_map[H5FD_MEM_NTYPES];
hid_t _memb_fapl[H5FD_MEM_NTYPES];
char _memb_name[H5FD_MEM_NTYPES][16];
const char *_memb_name_ptrs[H5FD_MEM_NTYPES];
haddr_t _memb_addr[H5FD_MEM_NTYPES];
static const char *letters = "Xsbrglo";
static const char *func="H5FDset_fapl_multi";
H5Eclear2(H5E_DEFAULT);
if(H5I_GENPROP_LST != H5Iget_type(fapl_id) ||
TRUE != H5Pisa_class(fapl_id, H5P_FILE_ACCESS))
H5Epush_ret(func, H5E_ERR_CLS, H5E_PLIST, H5E_BADVALUE, "not an access list", -1)
if (!memb_map) {
for (mt=H5FD_MEM_DEFAULT; mt<H5FD_MEM_NTYPES; mt=(H5FD_mem_t)(mt+1))
_memb_map[mt] = H5FD_MEM_DEFAULT;
memb_map = _memb_map;
}
if (!memb_fapl) {
for (mt=H5FD_MEM_DEFAULT; mt<H5FD_MEM_NTYPES; mt=(H5FD_mem_t)(mt+1))
_memb_fapl[mt] = H5Pcreate(H5P_FILE_ACCESS);
memb_fapl = _memb_fapl;
}
if (!memb_name) {
assert(strlen(letters)==H5FD_MEM_NTYPES);
for (mt=H5FD_MEM_DEFAULT; mt<H5FD_MEM_NTYPES; mt=(H5FD_mem_t)(mt+1)) {
sprintf(_memb_name[mt], "%%s-%c.h5", letters[mt]);
_memb_name_ptrs[mt] = _memb_name[mt];
}
memb_name = _memb_name_ptrs;
}
if (!memb_addr) {
for (mt=H5FD_MEM_DEFAULT; mt<H5FD_MEM_NTYPES; mt=(H5FD_mem_t)(mt+1))
_memb_addr[mt] = (hsize_t)(mt ? (mt - 1) : 0) * (HADDR_MAX / (H5FD_MEM_NTYPES-1));
memb_addr = _memb_addr;
}
for (mt=H5FD_MEM_DEFAULT; mt<H5FD_MEM_NTYPES; mt=(H5FD_mem_t)(mt+1)) {
mmt = memb_map[mt];
if (mmt<0 || mmt>=H5FD_MEM_NTYPES)
H5Epush_ret(func, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADRANGE, "file resource type out of range", -1)
if (H5FD_MEM_DEFAULT==mmt) mmt = mt;
if (H5P_DEFAULT!=memb_fapl[mmt] && TRUE!=H5Pisa_class(memb_fapl[mmt], H5P_FILE_ACCESS))
H5Epush_ret(func, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, "file resource type incorrect", -1)
if (!memb_name[mmt] || !memb_name[mmt][0])
H5Epush_ret(func, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, "file resource type not set", -1)
}
memset(&fa, 0, sizeof(H5FD_multi_fapl_t));
memcpy(fa.memb_map, memb_map, H5FD_MEM_NTYPES*sizeof(H5FD_mem_t));
memcpy(fa.memb_fapl, memb_fapl, H5FD_MEM_NTYPES*sizeof(hid_t));
memcpy(fa.memb_name, memb_name, H5FD_MEM_NTYPES*sizeof(char*));
memcpy(fa.memb_addr, memb_addr, H5FD_MEM_NTYPES*sizeof(haddr_t));
fa.relax = relax;
for (mt=H5FD_MEM_DEFAULT; mt<H5FD_MEM_NTYPES; mt=(H5FD_mem_t)(mt+1)) {
if(fa.memb_fapl[mt]==H5P_DEFAULT)
fa.memb_fapl[mt] = H5Pcreate(H5P_FILE_ACCESS);
}
return H5Pset_driver(fapl_id, H5FD_MULTI, &fa);
}
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)
{
const H5FD_multi_fapl_t *fa;
H5FD_mem_t mt;
static const char *func="H5FDget_fapl_multi";
H5Eclear2(H5E_DEFAULT);
if(H5I_GENPROP_LST != H5Iget_type(fapl_id) ||
TRUE != H5Pisa_class(fapl_id, H5P_FILE_ACCESS))
H5Epush_ret(func, H5E_ERR_CLS, H5E_PLIST, H5E_BADTYPE, "not an access list", -1)
if(H5FD_MULTI != H5Pget_driver(fapl_id))
H5Epush_ret(func, H5E_ERR_CLS, H5E_PLIST, H5E_BADVALUE, "incorrect VFL driver", -1)
if(NULL == (fa= (const H5FD_multi_fapl_t *)H5Pget_driver_info(fapl_id)))
H5Epush_ret(func, H5E_ERR_CLS, H5E_PLIST, H5E_BADVALUE, "bad VFL driver info", -1)
if (memb_map)
memcpy(memb_map, fa->memb_map, H5FD_MEM_NTYPES*sizeof(H5FD_mem_t));
if (memb_fapl) {
for (mt=H5FD_MEM_DEFAULT; mt<H5FD_MEM_NTYPES; mt=(H5FD_mem_t)(mt+1)) {
if (fa->memb_fapl[mt]>=0)
memb_fapl[mt] = H5Pcopy(fa->memb_fapl[mt]);
else
memb_fapl[mt] = fa->memb_fapl[mt];
}
}
if(memb_name) {
for(mt = H5FD_MEM_DEFAULT; mt < H5FD_MEM_NTYPES; mt = (H5FD_mem_t)(mt + 1)) {
if(fa->memb_name[mt])
memb_name[mt] = my_strdup(fa->memb_name[mt]);
else
memb_name[mt] = NULL;
}
}
if (memb_addr)
memcpy(memb_addr, fa->memb_addr, H5FD_MEM_NTYPES*sizeof(haddr_t));
if (relax)
*relax = fa->relax;
return 0;
}
static hsize_t
H5FD_multi_sb_size(H5FD_t *_file)
{
H5FD_multi_t *file = (H5FD_multi_t*)_file;
unsigned nseen = 0;
hsize_t nbytes = 8;
H5Eclear2(H5E_DEFAULT);
UNIQUE_MEMBERS(file->fa.memb_map, mt) {
nseen++;
} END_MEMBERS;
nbytes += nseen * 2 * 8;
UNIQUE_MEMBERS(file->fa.memb_map, mt) {
size_t n = strlen(file->fa.memb_name[mt])+1;
nbytes += (n+7) & ~((size_t)0x0007);
} END_MEMBERS;
return nbytes;
}
static herr_t
H5FD_multi_sb_encode(H5FD_t *_file, char *name,
unsigned char *buf)
{
H5FD_multi_t *file = (H5FD_multi_t*)_file;
haddr_t memb_eoa;
unsigned char *p;
size_t nseen;
size_t i;
H5FD_mem_t m;
static const char *func="H5FD_multi_sb_encode";
H5Eclear2(H5E_DEFAULT);
strncpy(name, "NCSAmulti", (size_t)8);
name[8] = '\0';
assert(7==H5FD_MEM_NTYPES);
for (m=H5FD_MEM_SUPER; m<H5FD_MEM_NTYPES; m=(H5FD_mem_t)(m+1)) {
buf[m-1] = (unsigned char)file->fa.memb_map[m];
}
buf[6] = 0;
buf[7] = 0;
nseen = 0;
p = buf+8;
assert(sizeof(haddr_t)<=8);
UNIQUE_MEMBERS(file->fa.memb_map, mt) {
memcpy(p, &(file->fa.memb_addr[mt]), sizeof(haddr_t));
p += sizeof(haddr_t);
memb_eoa = H5FDget_eoa(file->memb[mt], mt);
memcpy(p, &memb_eoa, sizeof(haddr_t));
p += sizeof(haddr_t);
nseen++;
} END_MEMBERS;
if (H5Tconvert(H5T_NATIVE_HADDR, H5T_STD_U64LE, nseen*2, buf+8, NULL, H5P_DEFAULT)<0)
H5Epush_ret(func, H5E_ERR_CLS, H5E_DATATYPE, H5E_CANTCONVERT, "can't convert superblock info", -1)
p = buf + 8 + nseen*2*8;
UNIQUE_MEMBERS(file->fa.memb_map, mt) {
size_t n = strlen(file->fa.memb_name[mt]) + 1;
strncpy((char *)p, file->fa.memb_name[mt], n);
p += n;
for (i=n; i%8; i++)
*p++ = '\0';
} END_MEMBERS;
return 0;
}
static herr_t
H5FD_multi_sb_decode(H5FD_t *_file, const char *name, const unsigned char *buf)
{
H5FD_multi_t *file = (H5FD_multi_t*)_file;
char x[2*H5FD_MEM_NTYPES*8];
H5FD_mem_t map[H5FD_MEM_NTYPES];
int i;
size_t nseen=0;
hbool_t map_changed=FALSE;
hbool_t in_use[H5FD_MEM_NTYPES];
const char *memb_name[H5FD_MEM_NTYPES];
haddr_t memb_addr[H5FD_MEM_NTYPES];
haddr_t memb_eoa[H5FD_MEM_NTYPES];
haddr_t *ap;
static const char *func="H5FD_multi_sb_decode";
H5Eclear2(H5E_DEFAULT);
if (strcmp(name, "NCSAmult"))
H5Epush_ret(func, H5E_ERR_CLS, H5E_FILE, H5E_BADVALUE, "invalid multi superblock", -1)
ALL_MEMBERS(mt) {
memb_addr[mt] = HADDR_UNDEF;
memb_eoa[mt] = HADDR_UNDEF;
memb_name[mt] = NULL;
} END_MEMBERS;
memset(map, 0, sizeof map);
for (i=0; i<6; i++) {
map[i+1] = (H5FD_mem_t)buf[i];
if (file->fa.memb_map[i+1]!=map[i+1])
map_changed=TRUE;
}
UNIQUE_MEMBERS(map, mt) {
nseen++;
} END_MEMBERS;
buf += 8;
assert(sizeof(haddr_t)<=8);
memcpy(x, buf, (nseen*2*8));
buf += nseen*2*8;
if (H5Tconvert(H5T_STD_U64LE, H5T_NATIVE_HADDR, nseen*2, x, NULL, H5P_DEFAULT)<0)
H5Epush_ret(func, H5E_ERR_CLS, H5E_DATATYPE, H5E_CANTCONVERT, "can't convert superblock info", -1)
ap = (haddr_t*)((void *)x);
UNIQUE_MEMBERS(map, mt) {
memb_addr[_unmapped] = *ap++;
memb_eoa[_unmapped] = *ap++;
} END_MEMBERS;
UNIQUE_MEMBERS(map, mt) {
size_t n = strlen((const char *)buf)+1;
memb_name[_unmapped] = (const char *)buf;
buf += (n+7) & ~((unsigned)0x0007);
} END_MEMBERS;
if (map_changed) {
ALL_MEMBERS(mt) {
file->fa.memb_map[mt] = map[mt];
} END_MEMBERS;
memset(in_use, 0, sizeof in_use);
UNIQUE_MEMBERS(map, mt) {
in_use[mt] = TRUE;
} END_MEMBERS;
ALL_MEMBERS(mt) {
if (!in_use[mt] && file->memb[mt]) {
(void)H5FDclose(file->memb[mt]);
file->memb[mt] = NULL;
}
file->fa.memb_map[mt] = map[mt];
} END_MEMBERS;
}
ALL_MEMBERS(mt) {
file->fa.memb_addr[mt] = memb_addr[mt];
if (memb_name[mt]) {
if (file->fa.memb_name[mt])
free(file->fa.memb_name[mt]);
file->fa.memb_name[mt] = my_strdup(memb_name[mt]);
}
} END_MEMBERS;
if (compute_next(file)<0)
H5Epush_ret(func, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, "compute_next() failed", -1)
if (open_members(file)<0)
H5Epush_ret(func, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, "open_members() failed", -1)
UNIQUE_MEMBERS(file->fa.memb_map, mt) {
if (file->memb[mt])
if(H5FDset_eoa(file->memb[mt], mt, memb_eoa[mt])<0)
H5Epush_ret(func, H5E_ERR_CLS, H5E_INTERNAL, H5E_CANTSET, "set_eoa() failed", -1)
file->memb_eoa[mt] = memb_eoa[mt];
} END_MEMBERS;
return 0;
}
static void *
H5FD_multi_fapl_get(H5FD_t *_file)
{
H5FD_multi_t *file = (H5FD_multi_t*)_file;
H5Eclear2(H5E_DEFAULT);
return H5FD_multi_fapl_copy(&(file->fa));
}
static void *
H5FD_multi_fapl_copy(const void *_old_fa)
{
const H5FD_multi_fapl_t *old_fa = (const H5FD_multi_fapl_t*)_old_fa;
H5FD_multi_fapl_t *new_fa = (H5FD_multi_fapl_t *)calloc(1, sizeof(H5FD_multi_fapl_t));
int nerrors = 0;
static const char *func="H5FD_multi_fapl_copy";
assert(new_fa);
H5Eclear2(H5E_DEFAULT);
memcpy(new_fa, old_fa, sizeof(H5FD_multi_fapl_t));
ALL_MEMBERS(mt) {
if (old_fa->memb_fapl[mt]>=0) {
if (H5Iinc_ref(old_fa->memb_fapl[mt]) < 0) {
nerrors++;
break;
}
new_fa->memb_fapl[mt] = old_fa->memb_fapl[mt];
}
if (old_fa->memb_name[mt]) {
new_fa->memb_name[mt] = my_strdup(old_fa->memb_name[mt]);
if (NULL == new_fa->memb_name[mt]) {
nerrors++;
break;
}
}
} END_MEMBERS;
if (nerrors) {
ALL_MEMBERS(mt) {
if (new_fa->memb_fapl[mt]>=0)
(void)H5Idec_ref(new_fa->memb_fapl[mt]);
if (new_fa->memb_name[mt])
free(new_fa->memb_name[mt]);
} END_MEMBERS;
free(new_fa);
H5Epush_ret(func, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, "can't release object on error", NULL)
}
return new_fa;
}
static herr_t
H5FD_multi_fapl_free(void *_fa)
{
H5FD_multi_fapl_t *fa = (H5FD_multi_fapl_t*)_fa;
static const char *func="H5FD_multi_fapl_free";
H5Eclear2(H5E_DEFAULT);
ALL_MEMBERS(mt) {
if (fa->memb_fapl[mt]>=0)
if(H5Idec_ref(fa->memb_fapl[mt])<0)
H5Epush_ret(func, H5E_ERR_CLS, H5E_FILE, H5E_CANTCLOSEOBJ, "can't close property list", -1)
if (fa->memb_name[mt])
free(fa->memb_name[mt]);
} END_MEMBERS;
free(fa);
return 0;
}
static H5FD_t *
H5FD_multi_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr)
{
H5FD_multi_t *file=NULL;
hid_t close_fapl=-1;
const H5FD_multi_fapl_t *fa;
H5FD_mem_t m;
static const char *func="H5FD_multi_open";
H5Eclear2(H5E_DEFAULT);
if (!name || !*name)
H5Epush_ret(func, H5E_ERR_CLS, H5E_ARGS, H5E_BADVALUE, "invalid file name", NULL)
if (0 == maxaddr || HADDR_UNDEF == maxaddr)
H5Epush_ret(func, H5E_ERR_CLS, H5E_ARGS, H5E_BADRANGE, "bogus maxaddr", NULL)
if(NULL == (file = (H5FD_multi_t *)calloc((size_t)1, sizeof(H5FD_multi_t))))
H5Epush_ret(func, H5E_ERR_CLS, H5E_RESOURCE, H5E_NOSPACE, "memory allocation failed", NULL)
if(H5P_FILE_ACCESS_DEFAULT == fapl_id || H5FD_MULTI != H5Pget_driver(fapl_id)) {
close_fapl = fapl_id = H5Pcreate(H5P_FILE_ACCESS);
if(H5Pset_fapl_multi(fapl_id, NULL, NULL, NULL, NULL, TRUE) < 0)
H5Epush_goto(func, H5E_ERR_CLS, H5E_FILE, H5E_CANTSET, "can't set property value", error)
}
fa = (const H5FD_multi_fapl_t *)H5Pget_driver_info(fapl_id);
assert(fa);
ALL_MEMBERS(mt) {
file->fa.memb_map[mt] = fa->memb_map[mt];
file->fa.memb_addr[mt] = fa->memb_addr[mt];
if (fa->memb_fapl[mt] >= 0)
H5Iinc_ref(fa->memb_fapl[mt]);
file->fa.memb_fapl[mt] = fa->memb_fapl[mt];
if (fa->memb_name[mt])
file->fa.memb_name[mt] = my_strdup(fa->memb_name[mt]);
else
file->fa.memb_name[mt] = NULL;
} END_MEMBERS;
file->fa.relax = fa->relax;
file->flags = flags;
file->name = my_strdup(name);
if (close_fapl >= 0)
if(H5Pclose(close_fapl) < 0)
H5Epush_goto(func, H5E_ERR_CLS, H5E_FILE, H5E_CANTCLOSEOBJ, "can't close property list", error)
if (compute_next(file) < 0)
H5Epush_goto(func, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, "compute_next() failed", error);
if (open_members(file) < 0)
H5Epush_goto(func, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, "open_members() failed", error);
if (H5FD_MEM_DEFAULT == (m = file->fa.memb_map[H5FD_MEM_SUPER]))
m = H5FD_MEM_SUPER;
if (NULL == file->memb[m])
goto error;
return (H5FD_t*)file;
error:
if (file) {
ALL_MEMBERS(mt) {
if (file->memb[mt]) (void)H5FDclose(file->memb[mt]);
if (file->fa.memb_fapl[mt] >= 0) (void)H5Idec_ref(file->fa.memb_fapl[mt]);
if (file->fa.memb_name[mt]) free(file->fa.memb_name[mt]);
} END_MEMBERS;
if (file->name)
free(file->name);
free(file);
}
return NULL;
}
static herr_t
H5FD_multi_close(H5FD_t *_file)
{
H5FD_multi_t *file = (H5FD_multi_t*)_file;
int nerrors=0;
static const char *func="H5FD_multi_close";
H5Eclear2(H5E_DEFAULT);
ALL_MEMBERS(mt) {
if (file->memb[mt]) {
if (H5FDclose(file->memb[mt])<0) {
nerrors++;
} else {
file->memb[mt] = NULL;
}
}
} END_MEMBERS;
if (nerrors)
H5Epush_ret(func, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, "error closing member files", -1)
ALL_MEMBERS(mt) {
if (file->fa.memb_fapl[mt]>=0) (void)H5Idec_ref(file->fa.memb_fapl[mt]);
if (file->fa.memb_name[mt]) free(file->fa.memb_name[mt]);
} END_MEMBERS;
free(file->name);
free(file);
return 0;
}
static int
H5FD_multi_cmp(const H5FD_t *_f1, const H5FD_t *_f2)
{
const H5FD_multi_t *f1 = (const H5FD_multi_t*)_f1;
const H5FD_multi_t *f2 = (const H5FD_multi_t*)_f2;
H5FD_mem_t out_mt = H5FD_MEM_DEFAULT;
int cmp=0;
H5Eclear2(H5E_DEFAULT);
ALL_MEMBERS(mt) {
out_mt = mt;
if(f1->memb[mt] && f2->memb[mt])
break;
if(!cmp) {
if(f1->memb[mt])
cmp = -1;
else if(f2->memb[mt])
cmp = 1;
}
} END_MEMBERS;
assert(cmp || out_mt<H5FD_MEM_NTYPES);
if(out_mt>=H5FD_MEM_NTYPES)
return cmp;
return H5FDcmp(f1->memb[out_mt], f2->memb[out_mt]);
}
static herr_t
H5FD_multi_query(const H5FD_t *_f, unsigned long *flags )
{
_f=_f;
if(flags) {
*flags = 0;
*flags |= H5FD_FEAT_DATA_SIEVE;
*flags |= H5FD_FEAT_AGGREGATE_SMALLDATA;
*flags |= H5FD_FEAT_USE_ALLOC_SIZE;
*flags |= H5FD_FEAT_PAGED_AGGR;
}
return(0);
}
static herr_t
H5FD_multi_get_type_map(const H5FD_t *_file, H5FD_mem_t *type_map)
{
const H5FD_multi_t *file = (const H5FD_multi_t*)_file;
memcpy(type_map, file->fa.memb_map, sizeof(file->fa.memb_map));
return(0);
}
static haddr_t
H5FD_multi_get_eoa(const H5FD_t *_file, H5FD_mem_t type)
{
const H5FD_multi_t *file = (const H5FD_multi_t*)_file;
haddr_t eoa = 0;
static const char *func="H5FD_multi_get_eoa";
H5Eclear2(H5E_DEFAULT);
if(H5FD_MEM_DEFAULT == type) {
UNIQUE_MEMBERS(file->fa.memb_map, mt) {
haddr_t memb_eoa;
if (file->memb[mt]) {
H5E_BEGIN_TRY {
memb_eoa = H5FDget_eoa(file->memb[mt], mt);
} H5E_END_TRY;
if(HADDR_UNDEF == memb_eoa)
H5Epush_ret(func, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, "member file has unknown eoa", HADDR_UNDEF)
if(memb_eoa>0)
memb_eoa += file->fa.memb_addr[mt];
} else if(file->fa.relax) {
memb_eoa = file->memb_next[mt];
assert(HADDR_UNDEF != memb_eoa);
} else {
H5Epush_ret(func, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, "bad eoa", HADDR_UNDEF)
}
if(memb_eoa > eoa)
eoa = memb_eoa;
} END_MEMBERS;
} else {
H5FD_mem_t mmt = file->fa.memb_map[type];
if(H5FD_MEM_DEFAULT == mmt)
mmt = type;
if(file->memb[mmt]) {
H5E_BEGIN_TRY {
eoa = H5FDget_eoa(file->memb[mmt], mmt);
} H5E_END_TRY;
if(HADDR_UNDEF == eoa)
H5Epush_ret(func, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, "member file has unknown eoa", HADDR_UNDEF)
if(eoa > 0)
eoa += file->fa.memb_addr[mmt];
} else if(file->fa.relax) {
eoa = file->memb_next[mmt];
assert(HADDR_UNDEF != eoa);
} else {
H5Epush_ret(func, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, "bad eoa", HADDR_UNDEF)
}
}
return eoa;
}
static herr_t
H5FD_multi_set_eoa(H5FD_t *_file, H5FD_mem_t type, haddr_t eoa)
{
H5FD_multi_t *file = (H5FD_multi_t*)_file;
H5FD_mem_t mmt;
herr_t status;
static const char *func="H5FD_multi_set_eoa";
H5Eclear2(H5E_DEFAULT);
mmt = file->fa.memb_map[type];
if(H5FD_MEM_DEFAULT == mmt) {
if(H5FD_MEM_DEFAULT == type)
mmt = H5FD_MEM_SUPER;
else
mmt = type;
}
if(H5FD_MEM_SUPER == mmt && file->memb_eoa[H5FD_MEM_SUPER] > 0 && eoa > (file->memb_next[H5FD_MEM_SUPER] / 2))
return 0;
assert(eoa >= file->fa.memb_addr[mmt]);
assert(eoa < file->memb_next[mmt]);
H5E_BEGIN_TRY {
status = H5FDset_eoa(file->memb[mmt], mmt, (eoa - file->fa.memb_addr[mmt]));
} H5E_END_TRY;
if(status < 0)
H5Epush_ret(func, H5E_ERR_CLS, H5E_FILE, H5E_BADVALUE, "member H5FDset_eoa failed", -1)
return 0;
}
static haddr_t
H5FD_multi_get_eof(const H5FD_t *_file, H5FD_mem_t type)
{
const H5FD_multi_t *file = (const H5FD_multi_t*)_file;
haddr_t eof = 0;
static const char *func="H5FD_multi_get_eof";
H5Eclear2(H5E_DEFAULT);
if(H5FD_MEM_DEFAULT == type) {
UNIQUE_MEMBERS(file->fa.memb_map, mt) {
haddr_t tmp_eof;
if(file->memb[mt]) {
H5E_BEGIN_TRY {
tmp_eof = H5FDget_eof(file->memb[mt], type);
} H5E_END_TRY;
if(HADDR_UNDEF == tmp_eof)
H5Epush_ret(func, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, "member file has unknown eof", HADDR_UNDEF)
if(tmp_eof > 0)
tmp_eof += file->fa.memb_addr[mt];
} else if(file->fa.relax) {
tmp_eof = file->memb_next[mt];
assert(HADDR_UNDEF != tmp_eof);
} else {
H5Epush_ret(func, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, "bad eof", HADDR_UNDEF)
}
if(tmp_eof > eof)
eof = tmp_eof;
} END_MEMBERS;
} else {
H5FD_mem_t mmt = file->fa.memb_map[type];
if(H5FD_MEM_DEFAULT == mmt)
mmt = type;
if(file->memb[mmt]) {
H5E_BEGIN_TRY {
eof = H5FDget_eof(file->memb[mmt], mmt);
} H5E_END_TRY;
if(HADDR_UNDEF == eof)
H5Epush_ret(func, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, "member file has unknown eof", HADDR_UNDEF)
if(eof > 0)
eof += file->fa.memb_addr[mmt];
} else if(file->fa.relax) {
eof = file->memb_next[mmt];
assert(HADDR_UNDEF != eof);
} else {
H5Epush_ret(func, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, "bad eof", HADDR_UNDEF)
}
}
return eof;
}
static herr_t
H5FD_multi_get_handle(H5FD_t *_file, hid_t fapl, void** file_handle)
{
H5FD_multi_t *file = (H5FD_multi_t *)_file;
H5FD_mem_t type, mmt;
static const char *func="H5FD_multi_get_handle";
if(H5Pget_multi_type(fapl, &type) < 0)
H5Epush_ret(func, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, "can't get data type for multi driver", -1)
if(type<H5FD_MEM_DEFAULT || type>=H5FD_MEM_NTYPES)
H5Epush_ret(func, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, "data type is out of range", -1)
mmt = file->fa.memb_map[type];
if(H5FD_MEM_DEFAULT==mmt) mmt = type;
return (H5FDget_vfd_handle(file->memb[mmt], fapl, file_handle));
}
static haddr_t
H5FD_multi_alloc(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, hsize_t size)
{
H5FD_multi_t *file = (H5FD_multi_t*)_file;
H5FD_mem_t mmt;
haddr_t addr;
static const char *func="H5FD_multi_alloc";
mmt = file->fa.memb_map[type];
if (H5FD_MEM_DEFAULT==mmt) mmt = type;
if(file->pub.paged_aggr) {
ALL_MEMBERS(mt) {
if(file->memb[mt])
file->memb[mt]->paged_aggr = file->pub.paged_aggr;
} END_MEMBERS;
}
if (HADDR_UNDEF==(addr=H5FDalloc(file->memb[mmt], mmt, dxpl_id, size)))
H5Epush_ret(func, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, "member file can't alloc", HADDR_UNDEF)
addr += file->fa.memb_addr[mmt];
return addr;
}
static herr_t
H5FD_multi_free(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, hsize_t size)
{
H5FD_multi_t *file = (H5FD_multi_t*)_file;
H5FD_mem_t mmt;
H5Eclear2(H5E_DEFAULT);
mmt = file->fa.memb_map[type];
if (H5FD_MEM_DEFAULT==mmt) mmt = type;
assert(addr>=file->fa.memb_addr[mmt]);
assert(addr+size<=file->memb_next[mmt]);
return H5FDfree(file->memb[mmt], mmt, dxpl_id, addr-file->fa.memb_addr[mmt], size);
}
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)
{
H5FD_multi_t *file = (H5FD_multi_t*)_file;
H5FD_mem_t mt, mmt, hi = H5FD_MEM_DEFAULT;
haddr_t start_addr = 0;
H5Eclear2(H5E_DEFAULT);
for(mt = H5FD_MEM_SUPER; mt < H5FD_MEM_NTYPES; mt = (H5FD_mem_t)(mt + 1)) {
mmt = file->fa.memb_map[mt];
if(H5FD_MEM_DEFAULT == mmt)
mmt = mt;
assert(mmt > 0 && mmt < H5FD_MEM_NTYPES);
if(file->fa.memb_addr[mmt] > addr)
continue;
if(file->fa.memb_addr[mmt] >= start_addr) {
start_addr = file->fa.memb_addr[mmt];
hi = mmt;
}
}
assert(hi > 0);
return H5FDread(file->memb[hi], type, dxpl_id, addr - start_addr, size, _buf);
}
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)
{
H5FD_multi_t *file = (H5FD_multi_t*)_file;
H5FD_mem_t mt, mmt, hi = H5FD_MEM_DEFAULT;
haddr_t start_addr = 0;
H5Eclear2(H5E_DEFAULT);
for(mt = H5FD_MEM_SUPER; mt < H5FD_MEM_NTYPES; mt = (H5FD_mem_t)(mt + 1)) {
mmt = file->fa.memb_map[mt];
if(H5FD_MEM_DEFAULT == mmt)
mmt = mt;
assert(mmt > 0 && mmt<H5FD_MEM_NTYPES);
if(file->fa.memb_addr[mmt] > addr)
continue;
if(file->fa.memb_addr[mmt] >= start_addr) {
start_addr = file->fa.memb_addr[mmt];
hi = mmt;
}
}
assert(hi > 0);
return H5FDwrite(file->memb[hi], type, dxpl_id, addr - start_addr, size, _buf);
}
static herr_t
H5FD_multi_flush(H5FD_t *_file, hid_t dxpl_id, hbool_t closing)
{
H5FD_multi_t *file = (H5FD_multi_t*)_file;
H5FD_mem_t mt;
int nerrors=0;
static const char *func="H5FD_multi_flush";
#if 0#endif
H5Eclear2(H5E_DEFAULT);
for (mt=H5FD_MEM_SUPER; mt<H5FD_MEM_NTYPES; mt=(H5FD_mem_t)(mt+1)) {
if (file->memb[mt]) {
H5E_BEGIN_TRY {
if (H5FDflush(file->memb[mt],dxpl_id,closing)<0) nerrors++;
} H5E_END_TRY;
}
}
if (nerrors)
H5Epush_ret(func, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, "error flushing member files", -1)
return 0;
}
static herr_t
H5FD_multi_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing)
{
H5FD_multi_t *file = (H5FD_multi_t*)_file;
H5FD_mem_t mt;
int nerrors=0;
static const char *func="H5FD_multi_truncate";
H5Eclear2(H5E_DEFAULT);
for(mt = H5FD_MEM_SUPER; mt < H5FD_MEM_NTYPES; mt = (H5FD_mem_t)(mt + 1)) {
if(file->memb[mt]) {
H5E_BEGIN_TRY {
if(H5FDtruncate(file->memb[mt], dxpl_id, closing) < 0)
nerrors++;
} H5E_END_TRY;
}
}
if(nerrors)
H5Epush_ret(func, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, "error truncating member files", -1)
return 0;
}
static herr_t
H5FD_multi_lock(H5FD_t *_file, hbool_t rw)
{
H5FD_multi_t *file = (H5FD_multi_t*)_file;
int nerrors = 0;
H5FD_mem_t out_mt;
static const char *func="H5FD_multi_unlock";
H5Eclear2(H5E_DEFAULT);
ALL_MEMBERS(mt) {
out_mt = mt;
if(file->memb[mt]) {
H5E_BEGIN_TRY {
if(H5FDlock(file->memb[mt], rw) < 0) {
nerrors++;
break;
}
} H5E_END_TRY;
}
} END_MEMBERS;
if(nerrors) {
H5FD_mem_t k;
for(k = H5FD_MEM_DEFAULT; k < out_mt; k = (H5FD_mem_t)(k + 1)) {
H5E_BEGIN_TRY {
if(H5FDunlock(file->memb[k]) < 0)
nerrors++;
} H5E_END_TRY;
}
}
if(nerrors)
H5Epush_ret(func, H5E_ERR_CLS, H5E_VFL, H5E_CANTLOCKFILE, "error locking member files", -1)
return 0;
}
static herr_t
H5FD_multi_unlock(H5FD_t *_file)
{
H5FD_multi_t *file = (H5FD_multi_t*)_file;
int nerrors=0;
static const char *func="H5FD_multi_unlock";
H5Eclear2(H5E_DEFAULT);
ALL_MEMBERS(mt) {
if(file->memb[mt])
if(H5FDunlock(file->memb[mt]) < 0)
nerrors++;
} END_MEMBERS;
if(nerrors)
H5Epush_ret(func, H5E_ERR_CLS, H5E_VFL, H5E_CANTUNLOCKFILE, "error unlocking member files", -1)
return 0;
}
static int
compute_next(H5FD_multi_t *file)
{
H5Eclear2(H5E_DEFAULT);
ALL_MEMBERS(mt) {
file->memb_next[mt] = HADDR_UNDEF;
} END_MEMBERS;
UNIQUE_MEMBERS(file->fa.memb_map, mt1) {
UNIQUE_MEMBERS2(file->fa.memb_map, mt2) {
if (file->fa.memb_addr[mt1]<file->fa.memb_addr[mt2] &&
(HADDR_UNDEF==file->memb_next[mt1] ||
file->memb_next[mt1]>file->fa.memb_addr[mt2])) {
file->memb_next[mt1] = file->fa.memb_addr[mt2];
}
} END_MEMBERS;
if (HADDR_UNDEF==file->memb_next[mt1]) {
file->memb_next[mt1] = HADDR_MAX;
}
} END_MEMBERS;
return 0;
}
H5_GCC_DIAG_OFF(format-nonliteral)
static int
open_members(H5FD_multi_t *file)
{
char tmp[H5FD_MULT_MAX_FILE_NAME_LEN];
int nerrors = 0;
static const char *func="(H5FD_multi)open_members";
H5Eclear2(H5E_DEFAULT);
UNIQUE_MEMBERS(file->fa.memb_map, mt) {
if(file->memb[mt])
continue;
assert(file->fa.memb_name[mt]);
sprintf(tmp, file->fa.memb_name[mt], file->name);
tmp[sizeof(tmp) - 1] = '\0';
H5E_BEGIN_TRY {
file->memb[mt] = H5FDopen(tmp, file->flags, file->fa.memb_fapl[mt], HADDR_UNDEF);
} H5E_END_TRY;
if(!file->memb[mt]) {
if(!file->fa.relax || (file->flags & H5F_ACC_RDWR))
nerrors++;
}
} END_MEMBERS;
if (nerrors)
H5Epush_ret(func, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, "error opening member files", -1)
return 0;
}
H5_GCC_DIAG_ON(format-nonliteral)
#ifdef _H5private_H
#error "Do not use HDF5 private definitions"
#endif