#include "H5FDdrvr_module.h"
#include "H5private.h"
#ifdef H5_HAVE_MIRROR_VFD
#include "H5Eprivate.h"
#include "H5Fprivate.h"
#include "H5FDprivate.h"
#include "H5FDmirror.h"
#include "H5FDmirror_priv.h"
#include "H5FLprivate.h"
#include "H5Iprivate.h"
#include "H5MMprivate.h"
#include "H5Pprivate.h"
static hid_t H5FD_MIRROR_g = 0;
typedef struct H5FD_mirror_t {
H5FD_t pub;
H5FD_mirror_fapl_t fa;
haddr_t eoa;
haddr_t eof;
int sock_fd;
H5FD_mirror_xmit_t xmit;
uint32_t xmit_i;
} H5FD_mirror_t;
#define MAXADDR (((haddr_t)1<<(8*sizeof(HDoff_t)-1))-1)
#define ADDR_OVERFLOW(A) (HADDR_UNDEF==(A) || ((A) & ~(haddr_t)MAXADDR))
#ifndef BSWAP_64
#define BSWAP_64(X) \
(uint64_t)( (((X) & 0x00000000000000FF) << 56) \
| (((X) & 0x000000000000FF00) << 40) \
| (((X) & 0x0000000000FF0000) << 24) \
| (((X) & 0x00000000FF000000) << 8) \
| (((X) & 0x000000FF00000000) >> 8) \
| (((X) & 0x0000FF0000000000) >> 24) \
| (((X) & 0x00FF000000000000) >> 40) \
| (((X) & 0xFF00000000000000) >> 56))
#endif
#define MIRROR_DEBUG_OP_CALLS 0
#define MIRROR_DEBUG_XMIT_BYTES 0
#if MIRROR_DEBUG_XMIT_BYTES
#define LOG_XMIT_BYTES(label, buf, len) do { \
ssize_t bytes_written = 0; \
const unsigned char *b = NULL; \
\
HDfprintf(stdout, "%s bytes:\n```\n", (label)); \
\
\
while ((len - bytes_written) >= 32) { \
b = (const unsigned char *)(buf) + bytes_written; \
HDfprintf(stdout, \
"%04zX %02X%02X%02X%02X %02X%02X%02X%02X" \
" %02X%02X%02X%02X %02X%02X%02X%02X" \
" %02X%02X%02X%02X %02X%02X%02X%02X" \
" %02X%02X%02X%02X %02X%02X%02X%02X\n", \
bytes_written, \
b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7], \
b[8], b[9], b[10],b[11], b[12],b[13],b[14],b[15], \
b[16],b[17],b[18],b[19], b[20],b[21],b[22],b[23], \
b[24],b[25],b[26],b[27], b[28],b[29],b[30],b[31]); \
bytes_written += 32; \
} \
\
\
if (len > bytes_written) { \
HDfprintf(stdout, "%04zX ", bytes_written); \
} \
\
\
while ((len - bytes_written) >= 4) { \
HDfprintf(stdout, " %02X%02X%02X%02X", \
(buf)[bytes_written], (buf)[bytes_written+1], \
(buf)[bytes_written+2], (buf)[bytes_written+3]); \
bytes_written += 4; \
} \
\
\
if (len > bytes_written) { \
HDfprintf(stdout, " "); \
} \
\
\
while (len > bytes_written) { \
HDfprintf(stdout, "%02X", (buf)[bytes_written++]); \
} \
\
\
HDfprintf(stdout, "\n"); \
HDfprintf(stdout, "```\n"); \
HDfflush(stdout); \
} while (0)
#else
#define LOG_XMIT_BYTES(label, buf, len)
#endif
#if MIRROR_DEBUG_OP_CALLS
#define LOG_OP_CALL(name) do { \
HDprintf("called %s()\n", (name)); \
HDfflush(stdout); \
} while (0)
#else
#define LOG_OP_CALL(name)
#endif
static herr_t H5FD__mirror_term(void);
static void *H5FD__mirror_fapl_get(H5FD_t *_file);
static void *H5FD__mirror_fapl_copy(const void *_old_fa);
static herr_t H5FD__mirror_fapl_free(void *_fa);
static haddr_t H5FD__mirror_get_eoa(const H5FD_t *_file, H5FD_mem_t type);
static herr_t H5FD__mirror_set_eoa(H5FD_t *_file, H5FD_mem_t type, haddr_t addr);
static haddr_t H5FD__mirror_get_eof(const H5FD_t *_file, H5FD_mem_t type);
static H5FD_t *H5FD__mirror_open(const char *name, unsigned flags,
hid_t fapl_id, haddr_t maxaddr);
static herr_t H5FD__mirror_close(H5FD_t *_file);
static herr_t H5FD__mirror_query(const H5FD_t *_file, unsigned long *flags);
static herr_t H5FD__mirror_write(H5FD_t *_file, H5FD_mem_t type, hid_t fapl_id,
haddr_t addr, size_t size, const void *buf);
static herr_t H5FD__mirror_read(H5FD_t *_file, H5FD_mem_t type, hid_t fapl_id,
haddr_t addr, size_t size, void *buf);
static herr_t H5FD__mirror_truncate(H5FD_t *_file, hid_t dxpl_id,
hbool_t closing);
static herr_t H5FD__mirror_lock(H5FD_t *_file, hbool_t rw);
static herr_t H5FD__mirror_unlock(H5FD_t *_file);
static herr_t H5FD__mirror_verify_reply(H5FD_mirror_t *file);
static const H5FD_class_t H5FD_mirror_g = {
"mirror",
MAXADDR,
H5F_CLOSE_WEAK,
H5FD__mirror_term,
NULL,
NULL,
NULL,
0,
H5FD__mirror_fapl_get,
H5FD__mirror_fapl_copy,
H5FD__mirror_fapl_free,
0,
NULL,
NULL,
H5FD__mirror_open,
H5FD__mirror_close,
NULL,
H5FD__mirror_query,
NULL,
NULL,
NULL,
H5FD__mirror_get_eoa,
H5FD__mirror_set_eoa,
H5FD__mirror_get_eof,
NULL,
H5FD__mirror_read,
H5FD__mirror_write,
NULL,
H5FD__mirror_truncate,
H5FD__mirror_lock,
H5FD__mirror_unlock,
H5FD_FLMAP_DICHOTOMY
};
H5FL_BLK_DEFINE_STATIC(xmit);
H5FL_DEFINE_STATIC(H5FD_mirror_t);
H5FL_DEFINE_STATIC(H5FD_mirror_xmit_open_t);
static herr_t
H5FD__init_package(void)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
LOG_OP_CALL(FUNC);
if(H5FD_mirror_init() < 0)
HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "unable to initialize mirror VFD");
done:
FUNC_LEAVE_NOAPI(ret_value)
}
hid_t
H5FD_mirror_init(void)
{
hid_t ret_value = H5I_INVALID_HID;
FUNC_ENTER_NOAPI(FAIL)
LOG_OP_CALL(FUNC);
if(H5I_VFL != H5I_get_type(H5FD_MIRROR_g))
H5FD_MIRROR_g = H5FD_register(&H5FD_mirror_g, sizeof(H5FD_class_t), FALSE);
ret_value = H5FD_MIRROR_g;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5FD__mirror_term(void)
{
FUNC_ENTER_STATIC_NOERR
H5FD_MIRROR_g = 0;
LOG_OP_CALL(FUNC);
FUNC_LEAVE_NOAPI(SUCCEED)
}
size_t
H5FD__mirror_xmit_decode_uint16(uint16_t *out, const unsigned char *_buf)
{
uint16_t n = 0;
LOG_OP_CALL(__func__);
HDassert(_buf && out);
HDmemcpy(&n, _buf, sizeof(n));
*out = (uint16_t)HDntohs(n);
return 2;
}
size_t
H5FD__mirror_xmit_decode_uint32(uint32_t *out, const unsigned char *_buf)
{
uint32_t n = 0;
LOG_OP_CALL(__func__);
HDassert(_buf && out);
HDmemcpy(&n, _buf, sizeof(n));
*out = (uint32_t)HDntohl(n);
return 4;
}
static hbool_t
is_host_little_endian(void)
{
union {
uint32_t u32;
uint8_t u8[4];
} echeck;
echeck.u32 = 0xA1B2C3D4;
if(echeck.u8[0] == 0xD4)
return TRUE;
else
return FALSE;
}
size_t
H5FD__mirror_xmit_decode_uint64(uint64_t *out, const unsigned char *_buf)
{
uint64_t n = 0;
LOG_OP_CALL(__func__);
HDassert(_buf && out);
HDmemcpy(&n, _buf, sizeof(n));
if(TRUE == is_host_little_endian())
*out = BSWAP_64(n);
else
*out = n;
return 8;
}
size_t
H5FD__mirror_xmit_decode_uint8(uint8_t *out, const unsigned char *_buf)
{
LOG_OP_CALL(__func__);
HDassert(_buf && out);
HDmemcpy(out, _buf, sizeof(uint8_t));
return 1;
}
size_t
H5FD__mirror_xmit_encode_uint16(unsigned char *_dest, uint16_t v)
{
uint16_t n = 0;
LOG_OP_CALL(__func__);
HDassert(_dest);
n = (uint16_t)HDhtons(v);
HDmemcpy(_dest, &n, sizeof(n));
return 2;
}
size_t
H5FD__mirror_xmit_encode_uint32(unsigned char *_dest, uint32_t v)
{
uint32_t n = 0;
LOG_OP_CALL(__func__);
HDassert(_dest);
n = (uint32_t)HDhtonl(v);
HDmemcpy(_dest, &n, sizeof(n));
return 4;
}
size_t
H5FD__mirror_xmit_encode_uint64(unsigned char *_dest, uint64_t v)
{
uint64_t n = v;
LOG_OP_CALL(__func__);
HDassert(_dest);
if(TRUE == is_host_little_endian())
n = BSWAP_64(v);
HDmemcpy(_dest, &n, sizeof(n));
return 8;
}
size_t
H5FD__mirror_xmit_encode_uint8(unsigned char *dest, uint8_t v)
{
LOG_OP_CALL(__func__);
HDassert(dest);
HDmemcpy(dest, &v, sizeof(v));
return 1;
}
size_t
H5FD_mirror_xmit_decode_header(H5FD_mirror_xmit_t *out,
const unsigned char *buf)
{
size_t n_eaten = 0;
LOG_OP_CALL(__func__);
HDassert(out && buf);
n_eaten += H5FD__mirror_xmit_decode_uint32(&(out->magic), &buf[n_eaten]);
n_eaten += H5FD__mirror_xmit_decode_uint8(&(out->version), &buf[n_eaten]);
n_eaten += H5FD__mirror_xmit_decode_uint32(&(out->session_token),
&buf[n_eaten]);
n_eaten += H5FD__mirror_xmit_decode_uint32(&(out->xmit_count),
&buf[n_eaten]);
n_eaten += H5FD__mirror_xmit_decode_uint8(&(out->op), &buf[n_eaten]);
HDassert(n_eaten == H5FD_MIRROR_XMIT_HEADER_SIZE);
return n_eaten;
}
size_t
H5FD_mirror_xmit_decode_lock(H5FD_mirror_xmit_lock_t *out,
const unsigned char *buf)
{
size_t n_eaten = 0;
LOG_OP_CALL(__func__);
HDassert(out && buf);
n_eaten += H5FD_mirror_xmit_decode_header(&(out->pub), buf);
n_eaten += H5FD__mirror_xmit_decode_uint64(&(out->rw), &buf[n_eaten]);
HDassert(n_eaten == H5FD_MIRROR_XMIT_LOCK_SIZE);
return n_eaten;
}
size_t
H5FD_mirror_xmit_decode_open(H5FD_mirror_xmit_open_t *out,
const unsigned char *buf)
{
size_t n_eaten = 0;
LOG_OP_CALL(__func__);
HDassert(out && buf);
n_eaten += H5FD_mirror_xmit_decode_header(&(out->pub), buf);
n_eaten += H5FD__mirror_xmit_decode_uint32(&(out->flags), &buf[n_eaten]);
n_eaten += H5FD__mirror_xmit_decode_uint64(&(out->maxaddr), &buf[n_eaten]);
n_eaten += H5FD__mirror_xmit_decode_uint64(&(out->size_t_blob),
&buf[n_eaten]);
HDassert((H5FD_MIRROR_XMIT_OPEN_SIZE - H5FD_MIRROR_XMIT_FILEPATH_MAX)
== n_eaten);
HDstrncpy(out->filename, (const char *)&buf[n_eaten],
H5FD_MIRROR_XMIT_FILEPATH_MAX - 1);
out->filename[H5FD_MIRROR_XMIT_FILEPATH_MAX - 1] = 0;
return H5FD_MIRROR_XMIT_OPEN_SIZE;
}
size_t
H5FD_mirror_xmit_decode_reply(H5FD_mirror_xmit_reply_t *out,
const unsigned char *buf)
{
size_t n_eaten = 0;
LOG_OP_CALL(__func__);
HDassert(out && buf);
n_eaten += H5FD_mirror_xmit_decode_header(&(out->pub), buf);
n_eaten += H5FD__mirror_xmit_decode_uint32(&(out->status), &buf[n_eaten]);
HDassert((H5FD_MIRROR_XMIT_REPLY_SIZE - H5FD_MIRROR_STATUS_MESSAGE_MAX)
== n_eaten);
HDstrncpy(out->message, (const char *)&buf[n_eaten],
H5FD_MIRROR_STATUS_MESSAGE_MAX - 1);
out->message[H5FD_MIRROR_STATUS_MESSAGE_MAX - 1] = 0;
return H5FD_MIRROR_XMIT_REPLY_SIZE;
}
size_t
H5FD_mirror_xmit_decode_set_eoa(H5FD_mirror_xmit_eoa_t *out,
const unsigned char *buf)
{
size_t n_eaten = 0;
LOG_OP_CALL(__func__);
HDassert(out && buf);
n_eaten += H5FD_mirror_xmit_decode_header(&(out->pub), buf);
n_eaten += H5FD__mirror_xmit_decode_uint8(&(out->type), &buf[n_eaten]);
n_eaten += H5FD__mirror_xmit_decode_uint64(&(out->eoa_addr), &buf[n_eaten]);
HDassert(n_eaten == H5FD_MIRROR_XMIT_EOA_SIZE);
return n_eaten;
}
size_t
H5FD_mirror_xmit_decode_write(H5FD_mirror_xmit_write_t *out,
const unsigned char *buf)
{
size_t n_eaten = 0;
LOG_OP_CALL(__func__);
HDassert(out && buf);
n_eaten += H5FD_mirror_xmit_decode_header(&(out->pub), buf);
n_eaten += H5FD__mirror_xmit_decode_uint8(&(out->type), &buf[n_eaten]);
n_eaten += H5FD__mirror_xmit_decode_uint64(&(out->offset), &buf[n_eaten]);
n_eaten += H5FD__mirror_xmit_decode_uint64(&(out->size), &buf[n_eaten]);
HDassert(n_eaten == H5FD_MIRROR_XMIT_WRITE_SIZE);
return n_eaten;
}
size_t
H5FD_mirror_xmit_encode_header(unsigned char *dest,
const H5FD_mirror_xmit_t *x)
{
size_t n_writ = 0;
LOG_OP_CALL(__func__);
HDassert(dest && x);
n_writ += H5FD__mirror_xmit_encode_uint32((dest+n_writ), x->magic);
n_writ += H5FD__mirror_xmit_encode_uint8((dest+n_writ), x->version);
n_writ += H5FD__mirror_xmit_encode_uint32((dest+n_writ), x->session_token);
n_writ += H5FD__mirror_xmit_encode_uint32((dest+n_writ), x->xmit_count);
n_writ += H5FD__mirror_xmit_encode_uint8((dest+n_writ), x->op);
HDassert(n_writ == H5FD_MIRROR_XMIT_HEADER_SIZE);
return n_writ;
}
size_t
H5FD_mirror_xmit_encode_lock(unsigned char *dest,
const H5FD_mirror_xmit_lock_t *x)
{
size_t n_writ = 0;
LOG_OP_CALL(__func__);
HDassert(dest && x);
n_writ += H5FD_mirror_xmit_encode_header(dest,
(const H5FD_mirror_xmit_t *)&(x->pub));
n_writ += H5FD__mirror_xmit_encode_uint64(&dest[n_writ], x->rw);
HDassert(n_writ == H5FD_MIRROR_XMIT_LOCK_SIZE);
return n_writ;
}
size_t
H5FD_mirror_xmit_encode_open(unsigned char *dest,
const H5FD_mirror_xmit_open_t *x)
{
size_t n_writ = 0;
LOG_OP_CALL(__func__);
HDassert(dest && x);
HDmemset(dest, 0, H5FD_MIRROR_XMIT_OPEN_SIZE);
n_writ += H5FD_mirror_xmit_encode_header(dest,
(const H5FD_mirror_xmit_t *)&(x->pub));
n_writ += H5FD__mirror_xmit_encode_uint32(&dest[n_writ], x->flags);
n_writ += H5FD__mirror_xmit_encode_uint64(&dest[n_writ], x->maxaddr);
n_writ += H5FD__mirror_xmit_encode_uint64(&dest[n_writ], x->size_t_blob);
HDassert((H5FD_MIRROR_XMIT_OPEN_SIZE - H5FD_MIRROR_XMIT_FILEPATH_MAX)
== n_writ);
HDstrncpy((char *)&dest[n_writ], x->filename, H5FD_MIRROR_XMIT_FILEPATH_MAX);
return H5FD_MIRROR_XMIT_OPEN_SIZE;
}
size_t
H5FD_mirror_xmit_encode_reply(unsigned char *dest,
const H5FD_mirror_xmit_reply_t *x)
{
size_t n_writ = 0;
LOG_OP_CALL(__func__);
HDassert(dest && x);
HDmemset(dest, 0, H5FD_MIRROR_XMIT_REPLY_SIZE);
n_writ += H5FD_mirror_xmit_encode_header(dest,
(const H5FD_mirror_xmit_t *)&(x->pub));
n_writ += H5FD__mirror_xmit_encode_uint32(&dest[n_writ], x->status);
HDassert((H5FD_MIRROR_XMIT_REPLY_SIZE - H5FD_MIRROR_STATUS_MESSAGE_MAX)
== n_writ);
HDstrncpy((char *)&dest[n_writ], x->message, H5FD_MIRROR_STATUS_MESSAGE_MAX);
return H5FD_MIRROR_XMIT_REPLY_SIZE;
}
size_t
H5FD_mirror_xmit_encode_set_eoa(unsigned char *dest,
const H5FD_mirror_xmit_eoa_t *x)
{
size_t n_writ = 0;
LOG_OP_CALL(__func__);
HDassert(dest && x);
n_writ += H5FD_mirror_xmit_encode_header(dest,
(const H5FD_mirror_xmit_t *)&(x->pub));
n_writ += H5FD__mirror_xmit_encode_uint8(&dest[n_writ], x->type);
n_writ += H5FD__mirror_xmit_encode_uint64(&dest[n_writ], x->eoa_addr);
HDassert(n_writ == H5FD_MIRROR_XMIT_EOA_SIZE);
return n_writ;
}
size_t
H5FD_mirror_xmit_encode_write(unsigned char *dest,
const H5FD_mirror_xmit_write_t *x)
{
size_t n_writ = 0;
LOG_OP_CALL(__func__);
HDassert(dest && x);
n_writ += H5FD_mirror_xmit_encode_header(dest,
(const H5FD_mirror_xmit_t *)&(x->pub));
n_writ += H5FD__mirror_xmit_encode_uint8(&dest[n_writ], x->type);
n_writ += H5FD__mirror_xmit_encode_uint64(&dest[n_writ], x->offset);
n_writ += H5FD__mirror_xmit_encode_uint64(&dest[n_writ], x->size);
HDassert(n_writ == H5FD_MIRROR_XMIT_WRITE_SIZE);
return n_writ;
}
H5_ATTR_PURE hbool_t
H5FD_mirror_xmit_is_close(const H5FD_mirror_xmit_t *xmit)
{
LOG_OP_CALL(__func__);
HDassert(xmit);
if((TRUE == H5FD_mirror_xmit_is_xmit(xmit)) && (H5FD_MIRROR_OP_CLOSE == xmit->op))
return TRUE;
return FALSE;
}
H5_ATTR_PURE hbool_t
H5FD_mirror_xmit_is_lock(const H5FD_mirror_xmit_lock_t *xmit)
{
LOG_OP_CALL(__func__);
HDassert(xmit);
if((TRUE == H5FD_mirror_xmit_is_xmit(&(xmit->pub))) && (H5FD_MIRROR_OP_LOCK == xmit->pub.op))
return TRUE;
return FALSE;
}
H5_ATTR_PURE hbool_t
H5FD_mirror_xmit_is_open(const H5FD_mirror_xmit_open_t *xmit)
{
LOG_OP_CALL(__func__);
HDassert(xmit);
if((TRUE == H5FD_mirror_xmit_is_xmit(&(xmit->pub))) && (H5FD_MIRROR_OP_OPEN == xmit->pub.op))
return TRUE;
return FALSE;
}
H5_ATTR_PURE hbool_t
H5FD_mirror_xmit_is_set_eoa(const H5FD_mirror_xmit_eoa_t *xmit)
{
LOG_OP_CALL(__func__);
HDassert(xmit);
if((TRUE == H5FD_mirror_xmit_is_xmit(&(xmit->pub))) && (H5FD_MIRROR_OP_SET_EOA == xmit->pub.op))
return TRUE;
return FALSE;
}
H5_ATTR_PURE hbool_t
H5FD_mirror_xmit_is_reply(const H5FD_mirror_xmit_reply_t *xmit)
{
LOG_OP_CALL(__func__);
HDassert(xmit);
if((TRUE == H5FD_mirror_xmit_is_xmit(&(xmit->pub))) && (H5FD_MIRROR_OP_REPLY == xmit->pub.op))
return TRUE;
return FALSE;
}
H5_ATTR_PURE hbool_t
H5FD_mirror_xmit_is_write(const H5FD_mirror_xmit_write_t *xmit)
{
LOG_OP_CALL(__func__);
HDassert(xmit);
if((TRUE == H5FD_mirror_xmit_is_xmit(&(xmit->pub))) && (H5FD_MIRROR_OP_WRITE == xmit->pub.op))
return TRUE;
return FALSE;
}
H5_ATTR_PURE hbool_t
H5FD_mirror_xmit_is_xmit(const H5FD_mirror_xmit_t *xmit)
{
LOG_OP_CALL(__func__);
HDassert(xmit);
if((H5FD_MIRROR_XMIT_MAGIC != xmit->magic) || (H5FD_MIRROR_XMIT_CURR_VERSION != xmit->version))
return FALSE;
return TRUE;
}
static herr_t
H5FD__mirror_verify_reply(H5FD_mirror_t *file)
{
unsigned char *xmit_buf = NULL;
struct H5FD_mirror_xmit_reply_t reply;
ssize_t read_ret = 0;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
LOG_OP_CALL(FUNC);
HDassert(file && file->sock_fd);
xmit_buf = H5FL_BLK_MALLOC(xmit, H5FD_MIRROR_XMIT_BUFFER_MAX);
if(NULL == xmit_buf)
HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, FAIL, "unable to allocate xmit buffer");
read_ret = HDread(file->sock_fd, xmit_buf, H5FD_MIRROR_XMIT_REPLY_SIZE);
if(read_ret < 0)
HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "unable to read reply");
if(read_ret != H5FD_MIRROR_XMIT_REPLY_SIZE)
HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "unexpected read size");
LOG_XMIT_BYTES("reply", xmit_buf, read_ret);
if(H5FD_mirror_xmit_decode_reply(&reply, xmit_buf) != H5FD_MIRROR_XMIT_REPLY_SIZE)
HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "unable to decode reply xmit");
if(H5FD_mirror_xmit_is_reply(&reply) != TRUE)
HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "xmit op code was not REPLY");
if(reply.pub.session_token != file->xmit.session_token)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "wrong session");
if(reply.pub.xmit_count != (file->xmit_i)++)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "xmit out of sync");
if(reply.status != H5FD_MIRROR_STATUS_OK)
HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "%s", (const char *)(reply.message));
done:
if(xmit_buf)
xmit_buf = H5FL_BLK_FREE(xmit, xmit_buf);
FUNC_LEAVE_NOAPI(ret_value);
}
static void *
H5FD__mirror_fapl_get(H5FD_t *_file)
{
H5FD_mirror_t *file = (H5FD_mirror_t *)_file;
H5FD_mirror_fapl_t *fa = NULL;
void *ret_value = NULL;
FUNC_ENTER_STATIC
LOG_OP_CALL(FUNC);
fa = (H5FD_mirror_fapl_t *)H5MM_calloc(sizeof(H5FD_mirror_fapl_t));
if(NULL == fa)
HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, NULL, "calloc failed");
HDmemcpy(fa, &(file->fa), sizeof(H5FD_mirror_fapl_t));
ret_value = fa;
done:
if(ret_value == NULL)
if(fa != NULL)
H5MM_xfree(fa);
FUNC_LEAVE_NOAPI(ret_value)
}
static void *
H5FD__mirror_fapl_copy(const void *_old_fa)
{
const H5FD_mirror_fapl_t *old_fa = (const H5FD_mirror_fapl_t *)_old_fa;
H5FD_mirror_fapl_t *new_fa = NULL;
void *ret_value = NULL;
FUNC_ENTER_STATIC
LOG_OP_CALL(FUNC);
new_fa = (H5FD_mirror_fapl_t *)H5MM_malloc(sizeof(H5FD_mirror_fapl_t));
if(new_fa == NULL)
HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, NULL, "memory allocation failed");
HDmemcpy(new_fa, old_fa, sizeof(H5FD_mirror_fapl_t));
ret_value = new_fa;
done:
if(ret_value == NULL)
if(new_fa != NULL)
H5MM_xfree(new_fa);
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5FD__mirror_fapl_free(void *_fa)
{
H5FD_mirror_fapl_t *fa = (H5FD_mirror_fapl_t*)_fa;
FUNC_ENTER_STATIC_NOERR
LOG_OP_CALL(FUNC);
HDassert(fa != NULL);
HDassert(fa->magic == H5FD_MIRROR_FAPL_MAGIC);
fa->magic += 1;
H5MM_xfree(fa);
FUNC_LEAVE_NOAPI(SUCCEED)
}
herr_t
H5Pget_fapl_mirror(hid_t fapl_id, H5FD_mirror_fapl_t *fa_out)
{
const H5FD_mirror_fapl_t *fa = NULL;
H5P_genplist_t *plist = NULL;
herr_t ret_value = SUCCEED;
FUNC_ENTER_API(FAIL)
H5TRACE2("e", "i*x", fapl_id, fa_out);
LOG_OP_CALL(FUNC);
if(NULL == fa_out)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "fa_out is NULL");
plist = H5P_object_verify(fapl_id, H5P_FILE_ACCESS);
if(NULL == plist)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list");
if(H5P_peek_driver(plist) != H5FD_MIRROR)
HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "incorrect VFL driver");
fa = (const H5FD_mirror_fapl_t *)H5P_peek_driver_info(plist);
if(NULL == fa)
HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "bad VFL driver info");
HDassert(fa->magic == H5FD_MIRROR_FAPL_MAGIC);
HDmemcpy(fa_out, fa, sizeof(H5FD_mirror_fapl_t));
done:
FUNC_LEAVE_API(ret_value);
}
herr_t
H5Pset_fapl_mirror(hid_t fapl_id, H5FD_mirror_fapl_t *fa)
{
H5P_genplist_t *plist = NULL;
herr_t ret_value = FAIL;
FUNC_ENTER_API(FAIL)
H5TRACE2("e", "i*x", fapl_id, fa);
LOG_OP_CALL(FUNC);
plist = H5P_object_verify(fapl_id, H5P_FILE_ACCESS);
if(NULL == plist)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list");
if(NULL == fa)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "null fapl_t pointer");
if(H5FD_MIRROR_FAPL_MAGIC != fa->magic)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid fapl_t magic");
if(H5FD_MIRROR_CURR_FAPL_T_VERSION != fa->version)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unknown fapl_t version");
ret_value = H5P_set_driver(plist, H5FD_MIRROR, (const void *)fa);
done:
FUNC_LEAVE_API(ret_value)
}
static H5FD_t *
H5FD__mirror_open(const char *name,
unsigned flags,
hid_t fapl_id,
haddr_t maxaddr)
{
int live_socket = -1;
struct sockaddr_in target_addr;
socklen_t addr_size;
unsigned char *xmit_buf = NULL;
H5FD_mirror_fapl_t fa;
H5FD_mirror_t *file = NULL;
H5FD_mirror_xmit_open_t *open_xmit = NULL;
H5FD_t *ret_value = NULL;
FUNC_ENTER_STATIC
LOG_OP_CALL(FUNC);
if(!name || !*name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "invalid file name");
if(HDstrlen(name) >= H5FD_MIRROR_XMIT_FILEPATH_MAX)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "filename is too long");
if(0 == maxaddr || HADDR_UNDEF == maxaddr)
HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, NULL, "bogus maxaddr");
if(ADDR_OVERFLOW(maxaddr))
HGOTO_ERROR(H5E_ARGS, H5E_OVERFLOW, NULL, "bogus maxaddr");
if(H5Pget_fapl_mirror(fapl_id, &fa) == FAIL)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "can't get config info");
if(H5FD_MIRROR_FAPL_MAGIC != fa.magic)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "invalid fapl magic");
if(H5FD_MIRROR_CURR_FAPL_T_VERSION != fa.version)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "invalid fapl version");
live_socket = HDsocket(AF_INET, SOCK_STREAM, 0);
if(live_socket < 0)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "can't create socket");
target_addr.sin_family = AF_INET;
target_addr.sin_port = HDhtons((uint16_t)fa.handshake_port);
target_addr.sin_addr.s_addr = HDinet_addr(fa.remote_ip);
HDmemset(target_addr.sin_zero, '\0', sizeof target_addr.sin_zero);
addr_size = sizeof(target_addr);
if(HDconnect(live_socket, (struct sockaddr *)&target_addr, addr_size) < 0)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "can't connect to remote server");
file = (H5FD_mirror_t *)H5FL_CALLOC(H5FD_mirror_t);
if(NULL == file)
HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, NULL, "unable to allocate file struct");
file->sock_fd = live_socket;
file->xmit_i = 0;
file->xmit.magic = H5FD_MIRROR_XMIT_MAGIC;
file->xmit.version = H5FD_MIRROR_XMIT_CURR_VERSION;
file->xmit.xmit_count = file->xmit_i++;
file->xmit.session_token = (uint32_t)(0x01020304 ^ file->sock_fd);
open_xmit = (H5FD_mirror_xmit_open_t *)H5FL_CALLOC(H5FD_mirror_xmit_open_t);
if(NULL == open_xmit)
HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, NULL, "unable to allocate open_xmit struct");
file->xmit.op = H5FD_MIRROR_OP_OPEN;
open_xmit->pub = file->xmit;
open_xmit->flags = (uint32_t)flags;
open_xmit->maxaddr = (uint64_t)maxaddr;
open_xmit->size_t_blob = (uint64_t)((size_t)(-1));
HDsnprintf(open_xmit->filename, H5FD_MIRROR_XMIT_FILEPATH_MAX-1, "%s", name);
xmit_buf = H5FL_BLK_MALLOC(xmit, H5FD_MIRROR_XMIT_BUFFER_MAX);
if(NULL == xmit_buf)
HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, NULL, "unable to allocate xmit buffer");
if(H5FD_mirror_xmit_encode_open(xmit_buf, open_xmit) != H5FD_MIRROR_XMIT_OPEN_SIZE)
HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, NULL, "unable to encode open");
LOG_XMIT_BYTES("open", xmit_buf, H5FD_MIRROR_XMIT_OPEN_SIZE);
if(HDwrite(file->sock_fd, xmit_buf, H5FD_MIRROR_XMIT_OPEN_SIZE) < 0)
HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, NULL, "unable to transmit open");
if(H5FD__mirror_verify_reply(file) == FAIL)
HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, NULL, "invalid reply");
ret_value = (H5FD_t *)file;
done:
if(NULL == ret_value) {
if(file)
file = H5FL_FREE(H5FD_mirror_t, file);
if(live_socket >= 0 && HDclose(live_socket) < 0)
HDONE_ERROR(H5E_VFL, H5E_CANTCLOSEFILE, NULL, "can't close socket");
}
if(open_xmit)
open_xmit = H5FL_FREE(H5FD_mirror_xmit_open_t, open_xmit);
if(xmit_buf)
xmit_buf = H5FL_BLK_FREE(xmit, xmit_buf);
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5FD__mirror_close(H5FD_t *_file)
{
H5FD_mirror_t *file = (H5FD_mirror_t *)_file;
unsigned char *xmit_buf = NULL;
int xmit_encoded = 0;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
LOG_OP_CALL(FUNC);
HDassert(file);
HDassert(file->sock_fd >= 0);
file->xmit.xmit_count = (file->xmit_i)++;
file->xmit.op = H5FD_MIRROR_OP_CLOSE;
xmit_buf = H5FL_BLK_MALLOC(xmit, H5FD_MIRROR_XMIT_BUFFER_MAX);
if(NULL == xmit_buf)
HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, FAIL, "unable to allocate xmit buffer");
if(H5FD_mirror_xmit_encode_header(xmit_buf, &(file->xmit)) != H5FD_MIRROR_XMIT_HEADER_SIZE)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to encode close");
xmit_encoded = 1;
LOG_XMIT_BYTES("close", xmit_buf, H5FD_MIRROR_XMIT_HEADER_SIZE);
if(HDwrite(file->sock_fd, xmit_buf, H5FD_MIRROR_XMIT_HEADER_SIZE) < 0)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to transmit close");
if(H5FD__mirror_verify_reply(file) == FAIL)
HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "invalid reply");
if(HDclose(file->sock_fd) < 0)
HGOTO_ERROR(H5E_VFL, H5E_CANTCLOSEFILE, FAIL, "can't close socket");
done:
if(ret_value == FAIL) {
if(xmit_encoded == 0) {
if(HDwrite(file->sock_fd, "GOODBYE", HDstrlen("GOODBYE")) < 0) {
HDONE_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to transmit close");
if(HDclose(file->sock_fd) < 0)
HDONE_ERROR(H5E_VFL, H5E_CANTCLOSEFILE, FAIL, "can't close socket");
file->sock_fd = -1;
}
else
if(HDshutdown(file->sock_fd, SHUT_WR) < 0)
HDONE_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "can't shutdown socket write: %s", HDstrerror(errno));
}
if(file->sock_fd >= 0)
if(HDclose(file->sock_fd) < 0)
HDONE_ERROR(H5E_VFL, H5E_CANTCLOSEFILE, FAIL, "can't close socket");
}
file = H5FL_FREE(H5FD_mirror_t, file);
if(xmit_buf)
xmit_buf = H5FL_BLK_FREE(xmit, xmit_buf);
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5FD__mirror_query(const H5FD_t H5_ATTR_UNUSED *_file, unsigned long *flags)
{
FUNC_ENTER_STATIC_NOERR;
LOG_OP_CALL(FUNC);
if(flags)
*flags = H5FD_FEAT_AGGREGATE_METADATA \
| H5FD_FEAT_ACCUMULATE_METADATA \
| H5FD_FEAT_DATA_SIEVE \
| H5FD_FEAT_AGGREGATE_SMALLDATA \
| H5FD_FEAT_POSIX_COMPAT_HANDLE \
| H5FD_FEAT_SUPPORTS_SWMR_IO \
| H5FD_FEAT_DEFAULT_VFD_COMPATIBLE;
FUNC_LEAVE_NOAPI(SUCCEED);
}
static haddr_t
H5FD__mirror_get_eoa(const H5FD_t *_file, H5FD_mem_t H5_ATTR_UNUSED type)
{
const H5FD_mirror_t *file = (const H5FD_mirror_t *)_file;
FUNC_ENTER_STATIC_NOERR
LOG_OP_CALL(FUNC);
HDassert(file);
FUNC_LEAVE_NOAPI(file->eoa)
}
static herr_t
H5FD__mirror_set_eoa(H5FD_t *_file, H5FD_mem_t type, haddr_t addr)
{
H5FD_mirror_xmit_eoa_t xmit_eoa;
unsigned char *xmit_buf = NULL;
H5FD_mirror_t *file = (H5FD_mirror_t *)_file;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
LOG_OP_CALL(FUNC);
HDassert(file);
file->eoa = addr;
file->xmit.xmit_count = (file->xmit_i)++;
file->xmit.op = H5FD_MIRROR_OP_SET_EOA;
xmit_eoa.pub = file->xmit;
xmit_eoa.type = (uint8_t)type;
xmit_eoa.eoa_addr = (uint64_t)addr;
xmit_buf = H5FL_BLK_MALLOC(xmit, H5FD_MIRROR_XMIT_BUFFER_MAX);
if(NULL == xmit_buf)
HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, FAIL, "unable to allocate xmit buffer");
if(H5FD_mirror_xmit_encode_set_eoa(xmit_buf, &xmit_eoa) != H5FD_MIRROR_XMIT_EOA_SIZE)
HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "unable to encode set-eoa");
LOG_XMIT_BYTES("set-eoa", xmit_buf, H5FD_MIRROR_XMIT_EOA_SIZE);
if(HDwrite(file->sock_fd, xmit_buf, H5FD_MIRROR_XMIT_EOA_SIZE) < 0)
HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "unable to transmit set-eoa");
if(H5FD__mirror_verify_reply(file) == FAIL)
HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "invalid reply");
done:
if(xmit_buf)
xmit_buf = H5FL_BLK_FREE(xmit, xmit_buf);
FUNC_LEAVE_NOAPI(ret_value)
}
static haddr_t
H5FD__mirror_get_eof(const H5FD_t *_file, H5FD_mem_t H5_ATTR_UNUSED type)
{
const H5FD_mirror_t *file = (const H5FD_mirror_t *)_file;
FUNC_ENTER_STATIC_NOERR
LOG_OP_CALL(FUNC);
HDassert(file);
FUNC_LEAVE_NOAPI(file->eof)
}
static herr_t
H5FD__mirror_read(H5FD_t H5_ATTR_UNUSED *_file, H5FD_mem_t H5_ATTR_UNUSED type,
hid_t H5_ATTR_UNUSED fapl_id, haddr_t H5_ATTR_UNUSED addr,
size_t H5_ATTR_UNUSED size, void H5_ATTR_UNUSED *buf)
{
FUNC_ENTER_STATIC_NOERR
LOG_OP_CALL(FUNC);
FUNC_LEAVE_NOAPI(FAIL)
}
static herr_t
H5FD__mirror_write(H5FD_t *_file, H5FD_mem_t type, hid_t H5_ATTR_UNUSED dxpl_id,
haddr_t addr, size_t size, const void *buf)
{
H5FD_mirror_xmit_write_t xmit_write;
unsigned char *xmit_buf = NULL;
H5FD_mirror_t *file = (H5FD_mirror_t *)_file;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
LOG_OP_CALL(FUNC);
HDassert(file);
HDassert(buf);
file->xmit.xmit_count = (file->xmit_i)++;
file->xmit.op = H5FD_MIRROR_OP_WRITE;
xmit_write.pub = file->xmit;
xmit_write.size = (uint64_t)size;
xmit_write.offset = (uint64_t)addr;
xmit_write.type = (uint8_t)type;
xmit_buf = H5FL_BLK_MALLOC(xmit, H5FD_MIRROR_XMIT_BUFFER_MAX);
if(NULL == xmit_buf)
HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, FAIL, "unable to allocate xmit buffer");
if(H5FD_mirror_xmit_encode_write(xmit_buf, &xmit_write) != H5FD_MIRROR_XMIT_WRITE_SIZE)
HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "unable to encode write");
LOG_XMIT_BYTES("write", xmit_buf, H5FD_MIRROR_XMIT_WRITE_SIZE);
if(HDwrite(file->sock_fd, xmit_buf, H5FD_MIRROR_XMIT_WRITE_SIZE) < 0)
HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "unable to transmit write");
if(H5FD__mirror_verify_reply(file) == FAIL)
HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "invalid reply");
if(HDwrite(file->sock_fd, buf, size) < 0)
HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "unable to transmit data");
if(H5FD__mirror_verify_reply(file) == FAIL)
HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "invalid reply");
done:
if(xmit_buf)
xmit_buf = H5FL_BLK_FREE(xmit, xmit_buf);
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5FD__mirror_truncate(H5FD_t *_file, hid_t H5_ATTR_UNUSED dxpl_id,
hbool_t H5_ATTR_UNUSED closing)
{
unsigned char *xmit_buf = NULL;
H5FD_mirror_t *file = (H5FD_mirror_t *)_file;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
LOG_OP_CALL(FUNC);
file->xmit.xmit_count = (file->xmit_i)++;
file->xmit.op = H5FD_MIRROR_OP_TRUNCATE;
xmit_buf = H5FL_BLK_MALLOC(xmit, H5FD_MIRROR_XMIT_BUFFER_MAX);
if(NULL == xmit_buf)
HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, FAIL, "unable to allocate xmit buffer");
if(H5FD_mirror_xmit_encode_header(xmit_buf, &(file->xmit)) != H5FD_MIRROR_XMIT_HEADER_SIZE)
HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "unable to encode truncate");
LOG_XMIT_BYTES("truncate", xmit_buf, H5FD_MIRROR_XMIT_HEADER_SIZE);
if(HDwrite(file->sock_fd, xmit_buf, H5FD_MIRROR_XMIT_HEADER_SIZE) < 0)
HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "unable to transmit truncate");
if(H5FD__mirror_verify_reply(file) == FAIL)
HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "invalid reply");
done:
if(xmit_buf)
xmit_buf = H5FL_BLK_FREE(xmit, xmit_buf);
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5FD__mirror_lock(H5FD_t *_file, hbool_t rw)
{
H5FD_mirror_xmit_lock_t xmit_lock;
unsigned char *xmit_buf = NULL;
H5FD_mirror_t *file = (H5FD_mirror_t *)_file;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
LOG_OP_CALL(FUNC);
file->xmit.xmit_count = (file->xmit_i)++;
file->xmit.op = H5FD_MIRROR_OP_LOCK;
xmit_lock.pub = file->xmit;
xmit_lock.rw = (uint64_t)rw;
xmit_buf = H5FL_BLK_MALLOC(xmit, H5FD_MIRROR_XMIT_BUFFER_MAX);
if(NULL == xmit_buf)
HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, FAIL, "unable to allocate xmit buffer");
if(H5FD_mirror_xmit_encode_lock(xmit_buf, &xmit_lock) != H5FD_MIRROR_XMIT_LOCK_SIZE)
HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "unable to encode lock");
LOG_XMIT_BYTES("lock", xmit_buf, H5FD_MIRROR_XMIT_LOCK_SIZE);
if(HDwrite(file->sock_fd, xmit_buf, H5FD_MIRROR_XMIT_LOCK_SIZE) < 0)
HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "unable to transmit lock");
if(H5FD__mirror_verify_reply(file) == FAIL)
HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "invalid reply");
done:
if(xmit_buf)
xmit_buf = H5FL_BLK_FREE(xmit, xmit_buf);
FUNC_LEAVE_NOAPI(ret_value);
}
static herr_t
H5FD__mirror_unlock(H5FD_t *_file)
{
unsigned char *xmit_buf = NULL;
H5FD_mirror_t *file = (H5FD_mirror_t *)_file;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
LOG_OP_CALL(FUNC);
file->xmit.xmit_count = (file->xmit_i)++;
file->xmit.op = H5FD_MIRROR_OP_UNLOCK;
xmit_buf = H5FL_BLK_MALLOC(xmit, H5FD_MIRROR_XMIT_BUFFER_MAX);
if(NULL == xmit_buf)
HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, FAIL, "unable to allocate xmit buffer");
if(H5FD_mirror_xmit_encode_header(xmit_buf, &(file->xmit)) != H5FD_MIRROR_XMIT_HEADER_SIZE)
HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "unable to encode unlock");
LOG_XMIT_BYTES("unlock", xmit_buf, H5FD_MIRROR_XMIT_HEADER_SIZE);
if(HDwrite(file->sock_fd, xmit_buf, H5FD_MIRROR_XMIT_HEADER_SIZE) < 0)
HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "unable to transmit unlock");
if(H5FD__mirror_verify_reply(file) == FAIL)
HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "invalid reply");
done:
if(xmit_buf)
xmit_buf = H5FL_BLK_FREE(xmit, xmit_buf);
FUNC_LEAVE_NOAPI(ret_value);
}
#endif