1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2  * Copyright by The HDF Group.                                               *
3  * All rights reserved.                                                      *
4  *                                                                           *
5  * This file is part of HDF5.  The full HDF5 copyright notice, including     *
6  * terms governing use, modification, and redistribution, is contained in    *
7  * the COPYING file, which can be found at the root of the source code       *
8  * distribution tree, or in https://www.hdfgroup.org/licenses.               *
9  * If you do not have access to either file, you may request a copy from     *
10  * help@hdfgroup.org.                                                        *
11  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
12 
13 /*
14  * Purpose: Transmit write-only operations to a receiver/writer process on
15  *          a remote host.
16  */
17 
18 #include "H5FDdrvr_module.h" /* This source code file is part of the H5FD driver module */
19 
20 #include "H5private.h" /* Generic Functions        */
21 
22 #ifdef H5_HAVE_MIRROR_VFD
23 
24 #include "H5Eprivate.h"      /* Error handling           */
25 #include "H5Fprivate.h"      /* File access              */
26 #include "H5FDprivate.h"     /* File drivers             */
27 #include "H5FDmirror.h"      /* "Mirror" definitions     */
28 #include "H5FDmirror_priv.h" /* Private header for the mirror VFD */
29 #include "H5FLprivate.h"     /* Free Lists               */
30 #include "H5Iprivate.h"      /* IDs                      */
31 #include "H5MMprivate.h"     /* Memory management        */
32 #include "H5Pprivate.h"      /* Property lists           */
33 
34 /* The driver identification number, initialized at runtime */
35 static hid_t H5FD_MIRROR_g = 0;
36 
37 /* Virtual file structure for a Mirror Driver */
38 typedef struct H5FD_mirror_t {
39     H5FD_t             pub;     /* Public stuff, must be first            */
40     H5FD_mirror_fapl_t fa;      /* Configuration structure                */
41     haddr_t            eoa;     /* End of allocated region                */
42     haddr_t            eof;     /* End of file; current file size         */
43     int                sock_fd; /* Handle of socket to remote operator    */
44     H5FD_mirror_xmit_t xmit;    /* Primary communication header           */
45     uint32_t           xmit_i;  /* Counter of transmission sent and rec'd */
46 } H5FD_mirror_t;
47 
48 /*
49  * These macros check for overflow of various quantities.  These macros
50  * assume that HDoff_t is signed and haddr_t and size_t are unsigned.
51  *
52  * ADDR_OVERFLOW:   Checks whether a file address of type `haddr_t'
53  *                  is too large to be represented by the second argument
54  *                  of the file seek function.
55  *
56  * SIZE_OVERFLOW:   Checks whether a buffer size of type `hsize_t' is too
57  *                  large to be represented by the `size_t' type.
58  *
59  * REGION_OVERFLOW: Checks whether an address and size pair describe data
60  *                  which can be addressed entirely by the second
61  *                  argument of the file seek function.
62  */
63 #define MAXADDR          (((haddr_t)1 << (8 * sizeof(HDoff_t) - 1)) - 1)
64 #define ADDR_OVERFLOW(A) (HADDR_UNDEF == (A) || ((A) & ~(haddr_t)MAXADDR))
65 
66 #ifndef BSWAP_64
67 #define BSWAP_64(X)                                                                                          \
68     (uint64_t)((((X)&0x00000000000000FF) << 56) | (((X)&0x000000000000FF00) << 40) |                         \
69                (((X)&0x0000000000FF0000) << 24) | (((X)&0x00000000FF000000) << 8) |                          \
70                (((X)&0x000000FF00000000) >> 8) | (((X)&0x0000FF0000000000) >> 24) |                          \
71                (((X)&0x00FF000000000000) >> 40) | (((X)&0xFF00000000000000) >> 56))
72 #endif /* BSWAP_64 */
73 
74 /* Debugging flabs for verbose tracing -- nonzero to enable */
75 #define MIRROR_DEBUG_OP_CALLS   0
76 #define MIRROR_DEBUG_XMIT_BYTES 0
77 
78 #if MIRROR_DEBUG_XMIT_BYTES
79 #define LOG_XMIT_BYTES(label, buf, len)                                                                      \
80     do {                                                                                                     \
81         ssize_t              bytes_written = 0;                                                              \
82         const unsigned char *b             = NULL;                                                           \
83                                                                                                              \
84         HDfprintf(stdout, "%s bytes:\n```\n", (label));                                                      \
85                                                                                                              \
86         /* print whole lines */                                                                              \
87         while ((len - bytes_written) >= 32) {                                                                \
88             b = (const unsigned char *)(buf) + bytes_written;                                                \
89             HDfprintf(stdout,                                                                                \
90                       "%04zX  %02X%02X%02X%02X %02X%02X%02X%02X"                                             \
91                       " %02X%02X%02X%02X %02X%02X%02X%02X"                                                   \
92                       " %02X%02X%02X%02X %02X%02X%02X%02X"                                                   \
93                       " %02X%02X%02X%02X %02X%02X%02X%02X\n",                                                \
94                       bytes_written, b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7], b[8], b[9], b[10],      \
95                       b[11], b[12], b[13], b[14], b[15], b[16], b[17], b[18], b[19], b[20], b[21], b[22],    \
96                       b[23], b[24], b[25], b[26], b[27], b[28], b[29], b[30], b[31]);                        \
97             bytes_written += 32;                                                                             \
98         }                                                                                                    \
99                                                                                                              \
100         /* start partial line */                                                                             \
101         if (len > bytes_written) {                                                                           \
102             HDfprintf(stdout, "%04zX ", bytes_written);                                                      \
103         }                                                                                                    \
104                                                                                                              \
105         /* partial line blocks */                                                                            \
106         while ((len - bytes_written) >= 4) {                                                                 \
107             HDfprintf(stdout, " %02X%02X%02X%02X", (buf)[bytes_written], (buf)[bytes_written + 1],           \
108                       (buf)[bytes_written + 2], (buf)[bytes_written + 3]);                                   \
109             bytes_written += 4;                                                                              \
110         }                                                                                                    \
111                                                                                                              \
112         /* block separator before partial block */                                                           \
113         if (len > bytes_written) {                                                                           \
114             HDfprintf(stdout, " ");                                                                          \
115         }                                                                                                    \
116                                                                                                              \
117         /* partial block individual bytes */                                                                 \
118         while (len > bytes_written) {                                                                        \
119             HDfprintf(stdout, "%02X", (buf)[bytes_written++]);                                               \
120         }                                                                                                    \
121                                                                                                              \
122         /* end partial line */                                                                               \
123         HDfprintf(stdout, "\n");                                                                             \
124         HDfprintf(stdout, "```\n");                                                                          \
125         HDfflush(stdout);                                                                                    \
126     } while (0)
127 #else
128 #define LOG_XMIT_BYTES(label, buf, len) /* no-op */
129 #endif                                  /* MIRROR_DEBUG_XMIT_BYTE */
130 
131 #if MIRROR_DEBUG_OP_CALLS
132 #define LOG_OP_CALL(name)                                                                                    \
133     do {                                                                                                     \
134         HDprintf("called %s()\n", (name));                                                                   \
135         HDfflush(stdout);                                                                                    \
136     } while (0)
137 #else
138 #define LOG_OP_CALL(name) /* no-op */
139 #endif                    /* MIRROR_DEBUG_OP_CALLS */
140 
141 /* Prototypes */
142 static herr_t  H5FD__mirror_term(void);
143 static void *  H5FD__mirror_fapl_get(H5FD_t *_file);
144 static void *  H5FD__mirror_fapl_copy(const void *_old_fa);
145 static herr_t  H5FD__mirror_fapl_free(void *_fa);
146 static haddr_t H5FD__mirror_get_eoa(const H5FD_t *_file, H5FD_mem_t type);
147 static herr_t  H5FD__mirror_set_eoa(H5FD_t *_file, H5FD_mem_t type, haddr_t addr);
148 static haddr_t H5FD__mirror_get_eof(const H5FD_t *_file, H5FD_mem_t type);
149 static H5FD_t *H5FD__mirror_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr);
150 static herr_t  H5FD__mirror_close(H5FD_t *_file);
151 static herr_t  H5FD__mirror_query(const H5FD_t *_file, unsigned long *flags);
152 static herr_t  H5FD__mirror_write(H5FD_t *_file, H5FD_mem_t type, hid_t fapl_id, haddr_t addr, size_t size,
153                                   const void *buf);
154 static herr_t  H5FD__mirror_read(H5FD_t *_file, H5FD_mem_t type, hid_t fapl_id, haddr_t addr, size_t size,
155                                  void *buf);
156 static herr_t  H5FD__mirror_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing);
157 static herr_t  H5FD__mirror_lock(H5FD_t *_file, hbool_t rw);
158 static herr_t  H5FD__mirror_unlock(H5FD_t *_file);
159 
160 static herr_t H5FD__mirror_verify_reply(H5FD_mirror_t *file);
161 
162 static const H5FD_class_t H5FD_mirror_g = {
163     "mirror",               /* name                 */
164     MAXADDR,                /* maxaddr              */
165     H5F_CLOSE_WEAK,         /* fc_degree            */
166     H5FD__mirror_term,      /* terminate            */
167     NULL,                   /* sb_size              */
168     NULL,                   /* sb_encode            */
169     NULL,                   /* sb_decode            */
170     0,                      /* fapl_size            */
171     H5FD__mirror_fapl_get,  /* fapl_get             */
172     H5FD__mirror_fapl_copy, /* fapl_copy            */
173     H5FD__mirror_fapl_free, /* fapl_free            */
174     0,                      /* dxpl_size            */
175     NULL,                   /* dxpl_copy            */
176     NULL,                   /* dxpl_free            */
177     H5FD__mirror_open,      /* open                 */
178     H5FD__mirror_close,     /* close                */
179     NULL,                   /* cmp                  */
180     H5FD__mirror_query,     /* query                */
181     NULL,                   /* get_type_map         */
182     NULL,                   /* alloc                */
183     NULL,                   /* free                 */
184     H5FD__mirror_get_eoa,   /* get_eoa              */
185     H5FD__mirror_set_eoa,   /* set_eoa              */
186     H5FD__mirror_get_eof,   /* get_eof              */
187     NULL,                   /* get_handle           */
188     H5FD__mirror_read,      /* read                 */
189     H5FD__mirror_write,     /* write                */
190     NULL,                   /* flush                */
191     H5FD__mirror_truncate,  /* truncate             */
192     H5FD__mirror_lock,      /* lock                 */
193     H5FD__mirror_unlock,    /* unlock               */
194     H5FD_FLMAP_DICHOTOMY    /* fl_map               */
195 };
196 
197 /* Declare a free list to manage the transmission buffers */
198 H5FL_BLK_DEFINE_STATIC(xmit);
199 
200 /* Declare a free list to manage the H5FD_mirror_t struct */
201 H5FL_DEFINE_STATIC(H5FD_mirror_t);
202 
203 /* Declare a free list to manage the H5FD_mirror_xmit_open_t struct */
204 H5FL_DEFINE_STATIC(H5FD_mirror_xmit_open_t);
205 
206 /*-------------------------------------------------------------------------
207  * Function:    H5FD__init_package
208  *
209  * Purpose:     Initializes any interface-specific data or routines.
210  *
211  * Return:      Non-negative on success/Negative on failure
212  *-------------------------------------------------------------------------
213  */
214 static herr_t
H5FD__init_package(void)215 H5FD__init_package(void)
216 {
217     herr_t ret_value = SUCCEED;
218 
219     FUNC_ENTER_STATIC
220 
221     LOG_OP_CALL(FUNC);
222 
223     if (H5FD_mirror_init() < 0)
224         HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "unable to initialize mirror VFD");
225 
226 done:
227     FUNC_LEAVE_NOAPI(ret_value)
228 } /* H5FD__init_package() */
229 
230 /* -------------------------------------------------------------------------
231  * Function:    H5FD_mirror_init
232  *
233  * Purpose:     Initialize this driver by registering the driver with the
234  *              library.
235  *
236  * Return:      Success:    The driver ID for the mirror driver.
237  *              Failure:    Negative
238  * -------------------------------------------------------------------------
239  */
240 hid_t
H5FD_mirror_init(void)241 H5FD_mirror_init(void)
242 {
243     hid_t ret_value = H5I_INVALID_HID;
244 
245     FUNC_ENTER_NOAPI(H5I_INVALID_HID)
246 
247     LOG_OP_CALL(FUNC);
248 
249     if (H5I_VFL != H5I_get_type(H5FD_MIRROR_g))
250         H5FD_MIRROR_g = H5FD_register(&H5FD_mirror_g, sizeof(H5FD_class_t), FALSE);
251 
252     ret_value = H5FD_MIRROR_g;
253 
254 done:
255     FUNC_LEAVE_NOAPI(ret_value)
256 } /* end H5FD_mirror_init() */
257 
258 /* ---------------------------------------------------------------------------
259  * Function:    H5FD__mirror_term
260  *
261  * Purpose:     Shut down the VFD
262  *
263  * Returns:     SUCCEED (Can't fail)
264  * ---------------------------------------------------------------------------
265  */
266 static herr_t
H5FD__mirror_term(void)267 H5FD__mirror_term(void)
268 {
269     FUNC_ENTER_STATIC_NOERR
270 
271     /* Reset VFL ID */
272     H5FD_MIRROR_g = 0;
273 
274     LOG_OP_CALL(FUNC);
275 
276     FUNC_LEAVE_NOAPI(SUCCEED)
277 } /* end H5FD__mirror_term() */
278 
279 /* ---------------------------------------------------------------------------
280  * Function:    H5FD__mirror_xmit_decode_uint16
281  *
282  * Purpose:     Extract a 16-bit integer in "network" (Big-Endian) word order
283  *              from the byte-buffer and return it with the local word order at
284  *              the destination pointer.
285  *
286  *              The programmer must ensure that the received buffer holds
287  *              at least the expected size of data.
288  *
289  * Return:      The number of bytes read from the buffer (2).
290  * ---------------------------------------------------------------------------
291  */
292 size_t
H5FD__mirror_xmit_decode_uint16(uint16_t * out,const unsigned char * _buf)293 H5FD__mirror_xmit_decode_uint16(uint16_t *out, const unsigned char *_buf)
294 {
295     uint16_t n = 0;
296 
297     LOG_OP_CALL(__func__);
298 
299     HDassert(_buf && out);
300 
301     H5MM_memcpy(&n, _buf, sizeof(n));
302     *out = (uint16_t)HDntohs(n);
303 
304     return 2; /* number of bytes eaten */
305 } /* end H5FD__mirror_xmit_decode_uint16() */
306 
307 /* ---------------------------------------------------------------------------
308  * Function:    H5FD__mirror_xmit_decode_uint32
309  *
310  * Purpose:     Extract a 32-bit integer in "network" (Big-Endian) word order
311  *              from the byte-buffer and return it with the local word order at
312  *              the destination pointer.
313  *
314  *              The programmer must ensure that the received buffer holds
315  *              at least the expected size of data.
316  *
317  * Return:      The number of bytes read from the buffer (4).
318  * ---------------------------------------------------------------------------
319  */
320 size_t
H5FD__mirror_xmit_decode_uint32(uint32_t * out,const unsigned char * _buf)321 H5FD__mirror_xmit_decode_uint32(uint32_t *out, const unsigned char *_buf)
322 {
323     uint32_t n = 0;
324 
325     LOG_OP_CALL(__func__);
326 
327     HDassert(_buf && out);
328 
329     H5MM_memcpy(&n, _buf, sizeof(n));
330     *out = (uint32_t)HDntohl(n);
331 
332     return 4; /* number of bytes eaten */
333 } /* end H5FD__mirror_xmit_decode_uint32() */
334 
335 /* ---------------------------------------------------------------------------
336  * Function:    is_host_little_endian
337  *
338  * Purpose:     Determine whether the host machine is is little-endian.
339  *
340  *              Store an intger with a known value, re-map the memory to a
341  *              character array, and inspect the array's contents.
342  *
343  * Return:      The number of bytes written to the buffer (8).
344  *
345  * Programmer:  Jacob Smith
346  *              2020-03-05
347  * ---------------------------------------------------------------------------
348  */
349 static hbool_t
is_host_little_endian(void)350 is_host_little_endian(void)
351 {
352     union {
353         uint32_t u32;
354         uint8_t  u8[4];
355     } echeck;
356     echeck.u32 = 0xA1B2C3D4;
357 
358     if (echeck.u8[0] == 0xD4)
359         return TRUE;
360     else
361         return FALSE;
362 } /* end is_host_little_endian() */
363 
364 /* ---------------------------------------------------------------------------
365  * Function:    H5FD__mirror_xmit_decode_uint64
366  *
367  * Purpose:     Extract a 64-bit integer in "network" (Big-Endian) word order
368  *              from the byte-buffer and return it with the local word order.
369  *
370  *              The programmer must ensure that the received buffer holds
371  *              at least the expected size of data.
372  *
373  *              WARNING: Does not accommodate other forms of endianness,
374  *              e.g. "middle-endian".
375  *
376  * Return:      The number of bytes written to the buffer (8).
377  * ---------------------------------------------------------------------------
378  */
379 size_t
H5FD__mirror_xmit_decode_uint64(uint64_t * out,const unsigned char * _buf)380 H5FD__mirror_xmit_decode_uint64(uint64_t *out, const unsigned char *_buf)
381 {
382     uint64_t n = 0;
383 
384     LOG_OP_CALL(__func__);
385 
386     HDassert(_buf && out);
387 
388     H5MM_memcpy(&n, _buf, sizeof(n));
389     if (TRUE == is_host_little_endian())
390         *out = BSWAP_64(n);
391     else
392         *out = n;
393 
394     return 8;
395 } /* end H5FD__mirror_xmit_decode_uint64() */
396 
397 /* ---------------------------------------------------------------------------
398  * Function:    H5FD__mirror_xmit_decode_uint8
399  *
400  * Purpose:     Extract a 8-bit integer in "network" (Big-Endian) word order
401  *              from the byte-buffer and return it with the local word order at
402  *              the destination pointer.
403  *              (yes, it's one byte).
404  *
405  * Return:      The number of bytes read from the buffer (1).
406  * ---------------------------------------------------------------------------
407  */
408 size_t
H5FD__mirror_xmit_decode_uint8(uint8_t * out,const unsigned char * _buf)409 H5FD__mirror_xmit_decode_uint8(uint8_t *out, const unsigned char *_buf)
410 {
411     LOG_OP_CALL(__func__);
412 
413     HDassert(_buf && out);
414 
415     H5MM_memcpy(out, _buf, sizeof(uint8_t));
416 
417     return 1; /* number of bytes eaten */
418 } /* end H5FD__mirror_xmit_decode_uint8() */
419 
420 /* ---------------------------------------------------------------------------
421  * Function:    H5FD__mirror_xmit_encode_uint16
422  *
423  * Purpose:     Encode a 16-bit integer in "network" (Big-Endian) word order
424  *              in place in the destination bytes-buffer.
425  *
426  *              The programmer must ensure that the destination buffer is
427  *              large enough to hold the expected data.
428  *
429  * Return:      The number of bytes written to the buffer (2).
430  * ---------------------------------------------------------------------------
431  */
432 size_t
H5FD__mirror_xmit_encode_uint16(unsigned char * _dest,uint16_t v)433 H5FD__mirror_xmit_encode_uint16(unsigned char *_dest, uint16_t v)
434 {
435     uint16_t n = 0;
436 
437     LOG_OP_CALL(__func__);
438 
439     HDassert(_dest);
440 
441     n = (uint16_t)HDhtons(v);
442     H5MM_memcpy(_dest, &n, sizeof(n));
443 
444     return 2;
445 } /* end H5FD__mirror_xmit_encode_uint16() */
446 
447 /* ---------------------------------------------------------------------------
448  * Function:    H5FD__mirror_xmit_encode_uint32
449  *
450  * Purpose:     Encode a 32-bit integer in "network" (Big-Endian) word order
451  *              in place in the destination bytes-buffer.
452  *
453  *              The programmer must ensure that the destination buffer is
454  *              large enough to hold the expected data.
455  *
456  * Return:      The number of bytes written to the buffer (4).
457  * ---------------------------------------------------------------------------
458  */
459 size_t
H5FD__mirror_xmit_encode_uint32(unsigned char * _dest,uint32_t v)460 H5FD__mirror_xmit_encode_uint32(unsigned char *_dest, uint32_t v)
461 {
462     uint32_t n = 0;
463 
464     LOG_OP_CALL(__func__);
465 
466     HDassert(_dest);
467 
468     n = (uint32_t)HDhtonl(v);
469     H5MM_memcpy(_dest, &n, sizeof(n));
470 
471     return 4;
472 } /* end H5FD__mirror_xmit_encode_uint32() */
473 
474 /* ---------------------------------------------------------------------------
475  * Function:    H5FD__mirror_xmit_encode_uint64
476  *
477  * Purpose:     Encode a 64-bit integer in "network" (Big-Endian) word order
478  *              in place in the destination bytes-buffer.
479  *
480  *              The programmer must ensure that the destination buffer is
481  *              large enough to hold the expected data.
482  *
483  * Return:      The number of bytes written to the buffer (8).
484  * ---------------------------------------------------------------------------
485  */
486 size_t
H5FD__mirror_xmit_encode_uint64(unsigned char * _dest,uint64_t v)487 H5FD__mirror_xmit_encode_uint64(unsigned char *_dest, uint64_t v)
488 {
489     uint64_t n = v;
490 
491     LOG_OP_CALL(__func__);
492 
493     HDassert(_dest);
494 
495     if (TRUE == is_host_little_endian())
496         n = BSWAP_64(v);
497     H5MM_memcpy(_dest, &n, sizeof(n));
498 
499     return 8;
500 } /* H5FD__mirror_xmit_encode_uint64() */
501 
502 /* ---------------------------------------------------------------------------
503  * Function:    H5FD__mirror_xmit_encode_uint8
504  *
505  * Purpose:     Encode a 8-bit integer in "network" (Big-Endian) word order
506  *              in place in the destination bytes-buffer.
507  *              (yes, it's one byte).
508  *
509  *              The programmer must ensure that the destination buffer is
510  *              large enough to hold the expected data.
511  *
512  * Return:      The number of bytes read from the buffer (1).
513  * ---------------------------------------------------------------------------
514  */
515 size_t
H5FD__mirror_xmit_encode_uint8(unsigned char * dest,uint8_t v)516 H5FD__mirror_xmit_encode_uint8(unsigned char *dest, uint8_t v)
517 {
518     LOG_OP_CALL(__func__);
519 
520     HDassert(dest);
521 
522     H5MM_memcpy(dest, &v, sizeof(v));
523 
524     return 1;
525 } /* end H5FD__mirror_xmit_encode_uint8() */
526 
527 /* ---------------------------------------------------------------------------
528  * Function:    H5FD_mirror_xmit_decode_header
529  *
530  * Purpose:     Extract a mirror_xmit_t "header" from the bytes-buffer.
531  *
532  *              Fields will be lifted from the buffer and stored in the
533  *              target structure, using in the correct location (different
534  *              systems may insert different padding between components) and
535  *              word order (Big- vs Little-Endian).
536  *
537  *              The resulting structure should be sanity-checked with
538  *              H5FD_mirror_xmit_is_xmit() before use.
539  *
540  *              The programmer must ensure that the received buffer holds
541  *              at least the expected size of data.
542  *
543  * Return:      The number of bytes consumed from the buffer.
544  * ---------------------------------------------------------------------------
545  */
546 size_t
H5FD_mirror_xmit_decode_header(H5FD_mirror_xmit_t * out,const unsigned char * buf)547 H5FD_mirror_xmit_decode_header(H5FD_mirror_xmit_t *out, const unsigned char *buf)
548 {
549     size_t n_eaten = 0;
550 
551     LOG_OP_CALL(__func__);
552 
553     HDassert(out && buf);
554 
555     n_eaten += H5FD__mirror_xmit_decode_uint32(&(out->magic), &buf[n_eaten]);
556     n_eaten += H5FD__mirror_xmit_decode_uint8(&(out->version), &buf[n_eaten]);
557     n_eaten += H5FD__mirror_xmit_decode_uint32(&(out->session_token), &buf[n_eaten]);
558     n_eaten += H5FD__mirror_xmit_decode_uint32(&(out->xmit_count), &buf[n_eaten]);
559     n_eaten += H5FD__mirror_xmit_decode_uint8(&(out->op), &buf[n_eaten]);
560     HDassert(n_eaten == H5FD_MIRROR_XMIT_HEADER_SIZE);
561 
562     return n_eaten;
563 } /* end H5FD_mirror_xmit_decode_header() */
564 
565 /* ---------------------------------------------------------------------------
566  * Function:    H5FD_mirror_xmit_decode_lock
567  *
568  * Purpose:     Extract a mirror_xmit_lock_t from the bytes-buffer.
569  *
570  *              Fields will be lifted from the buffer and stored in the
571  *              target structure, using in the correct location (different
572  *              systems may insert different padding between components) and
573  *              word order (Big- vs Little-Endian).
574  *
575  *              The programmer must ensure that the received buffer holds
576  *              at least the expected size of data.
577  *
578  *              The resulting structure should be sanity-checked with
579  *              H5FD_mirror_xmit_is_lock() before use.
580  *
581  * Return:      The number of bytes consumed from the buffer.
582  * ---------------------------------------------------------------------------
583  */
584 size_t
H5FD_mirror_xmit_decode_lock(H5FD_mirror_xmit_lock_t * out,const unsigned char * buf)585 H5FD_mirror_xmit_decode_lock(H5FD_mirror_xmit_lock_t *out, const unsigned char *buf)
586 {
587     size_t n_eaten = 0;
588 
589     LOG_OP_CALL(__func__);
590 
591     HDassert(out && buf);
592 
593     n_eaten += H5FD_mirror_xmit_decode_header(&(out->pub), buf);
594     n_eaten += H5FD__mirror_xmit_decode_uint64(&(out->rw), &buf[n_eaten]);
595     HDassert(n_eaten == H5FD_MIRROR_XMIT_LOCK_SIZE);
596 
597     return n_eaten;
598 } /* end H5FD_mirror_xmit_decode_lock() */
599 
600 /* ---------------------------------------------------------------------------
601  * Function:    H5FD_mirror_xmit_decode_open
602  *
603  * Purpose:     Extract a mirror_xmit_open_t from the bytes-buffer.
604  *
605  *              Fields will be lifted from the buffer and stored in the
606  *              target structure, using in the correct location (different
607  *              systems may insert different padding between components) and
608  *              word order (Big- vs Little-Endian).
609  *
610  *              The programmer must ensure that the received buffer holds
611  *              at least the expected size of data.
612  *
613  *              The resulting structure should be sanity-checked with
614  *              H5FD_mirror_xmit_is_open() before use.
615  *
616  * Return:      The maximum number of bytes that this decoding operation might
617  *              have consumed from the buffer.
618  * ---------------------------------------------------------------------------
619  */
620 size_t
H5FD_mirror_xmit_decode_open(H5FD_mirror_xmit_open_t * out,const unsigned char * buf)621 H5FD_mirror_xmit_decode_open(H5FD_mirror_xmit_open_t *out, const unsigned char *buf)
622 {
623     size_t n_eaten = 0;
624 
625     LOG_OP_CALL(__func__);
626 
627     HDassert(out && buf);
628 
629     n_eaten += H5FD_mirror_xmit_decode_header(&(out->pub), buf);
630     n_eaten += H5FD__mirror_xmit_decode_uint32(&(out->flags), &buf[n_eaten]);
631     n_eaten += H5FD__mirror_xmit_decode_uint64(&(out->maxaddr), &buf[n_eaten]);
632     n_eaten += H5FD__mirror_xmit_decode_uint64(&(out->size_t_blob), &buf[n_eaten]);
633     HDassert((H5FD_MIRROR_XMIT_OPEN_SIZE - H5FD_MIRROR_XMIT_FILEPATH_MAX) == n_eaten);
634     HDstrncpy(out->filename, (const char *)&buf[n_eaten], H5FD_MIRROR_XMIT_FILEPATH_MAX - 1);
635     out->filename[H5FD_MIRROR_XMIT_FILEPATH_MAX - 1] = 0; /* force final NULL */
636 
637     return H5FD_MIRROR_XMIT_OPEN_SIZE;
638 } /* end H5FD_mirror_xmit_decode_open() */
639 
640 /* ---------------------------------------------------------------------------
641  * Function:    H5FD_mirror_xmit_decode_reply
642  *
643  * Purpose:     Extract a mirror_xmit_reply_t from the bytes-buffer.
644  *
645  *              Fields will be lifted from the buffer and stored in the
646  *              target structure, using in the correct location (different
647  *              systems may insert different padding between components) and
648  *              word order (Big- vs Little-Endian).
649  *
650  *              The programmer must ensure that the received buffer holds
651  *              at least the expected size of data.
652  *
653  *              The resulting structure should be sanity-checked with
654  *              H5FD_mirror_xmit_is_reply() before use.
655  *
656  * Return:      The maximum number of bytes that this decoding operation might
657  *              have consumed from the buffer.
658  * ---------------------------------------------------------------------------
659  */
660 size_t
H5FD_mirror_xmit_decode_reply(H5FD_mirror_xmit_reply_t * out,const unsigned char * buf)661 H5FD_mirror_xmit_decode_reply(H5FD_mirror_xmit_reply_t *out, const unsigned char *buf)
662 {
663     size_t n_eaten = 0;
664 
665     LOG_OP_CALL(__func__);
666 
667     HDassert(out && buf);
668 
669     n_eaten += H5FD_mirror_xmit_decode_header(&(out->pub), buf);
670     n_eaten += H5FD__mirror_xmit_decode_uint32(&(out->status), &buf[n_eaten]);
671     HDassert((H5FD_MIRROR_XMIT_REPLY_SIZE - H5FD_MIRROR_STATUS_MESSAGE_MAX) == n_eaten);
672     HDstrncpy(out->message, (const char *)&buf[n_eaten], H5FD_MIRROR_STATUS_MESSAGE_MAX - 1);
673     out->message[H5FD_MIRROR_STATUS_MESSAGE_MAX - 1] = 0; /* force NULL term */
674 
675     return H5FD_MIRROR_XMIT_REPLY_SIZE;
676 } /* end H5FD_mirror_xmit_decode_reply() */
677 
678 /* ---------------------------------------------------------------------------
679  * Function:    H5FD_mirror_xmit_decode_set_eoa
680  *
681  * Purpose:     Extract a mirror_xmit_eoa_t from the bytes-buffer.
682  *
683  *              Fields will be lifted from the buffer and stored in the
684  *              target structure, using in the correct location (different
685  *              systems may insert different padding between components) and
686  *              word order (Big- vs Little-Endian).
687  *
688  *              The programmer must ensure that the received buffer holds
689  *              at least the expected size of data.
690  *
691  *              The resulting structure should be sanity-checked with
692  *              H5FD_mirror_xmit_is_set_eoa() before use.
693  *
694  * Return:      The number of bytes consumed from the buffer.
695  * ---------------------------------------------------------------------------
696  */
697 size_t
H5FD_mirror_xmit_decode_set_eoa(H5FD_mirror_xmit_eoa_t * out,const unsigned char * buf)698 H5FD_mirror_xmit_decode_set_eoa(H5FD_mirror_xmit_eoa_t *out, const unsigned char *buf)
699 {
700     size_t n_eaten = 0;
701 
702     LOG_OP_CALL(__func__);
703 
704     HDassert(out && buf);
705 
706     n_eaten += H5FD_mirror_xmit_decode_header(&(out->pub), buf);
707     n_eaten += H5FD__mirror_xmit_decode_uint8(&(out->type), &buf[n_eaten]);
708     n_eaten += H5FD__mirror_xmit_decode_uint64(&(out->eoa_addr), &buf[n_eaten]);
709     HDassert(n_eaten == H5FD_MIRROR_XMIT_EOA_SIZE);
710 
711     return n_eaten;
712 } /* end H5FD_mirror_xmit_decode_set_eoa() */
713 
714 /* ---------------------------------------------------------------------------
715  * Function:    H5FD_mirror_xmit_decode_write
716  *
717  * Purpose:     Extract a mirror_xmit_write_t from the bytes-buffer.
718  *
719  *              Fields will be lifted from the buffer and stored in the
720  *              target structure, using in the correct location (different
721  *              systems may insert different padding between components) and
722  *              word order (Big- vs Little-Endian).
723  *
724  *              The programmer must ensure that the received buffer holds
725  *              at least the expected size of data.
726  *
727  *              The resulting structure should be sanity-checked with
728  *              H5FD_mirror_xmit_is_write() before use.
729  *
730  * Return:      The number of bytes consumed from the buffer.
731  * ---------------------------------------------------------------------------
732  */
733 size_t
H5FD_mirror_xmit_decode_write(H5FD_mirror_xmit_write_t * out,const unsigned char * buf)734 H5FD_mirror_xmit_decode_write(H5FD_mirror_xmit_write_t *out, const unsigned char *buf)
735 {
736     size_t n_eaten = 0;
737 
738     LOG_OP_CALL(__func__);
739 
740     HDassert(out && buf);
741 
742     n_eaten += H5FD_mirror_xmit_decode_header(&(out->pub), buf);
743     n_eaten += H5FD__mirror_xmit_decode_uint8(&(out->type), &buf[n_eaten]);
744     n_eaten += H5FD__mirror_xmit_decode_uint64(&(out->offset), &buf[n_eaten]);
745     n_eaten += H5FD__mirror_xmit_decode_uint64(&(out->size), &buf[n_eaten]);
746     HDassert(n_eaten == H5FD_MIRROR_XMIT_WRITE_SIZE);
747 
748     return n_eaten;
749 } /* end H5FD_mirror_xmit_decode_write() */
750 
751 /* ---------------------------------------------------------------------------
752  * Function:    H5FD_mirror_xmit_encode_header
753  *
754  * Purpose:     Encode a mirror_xmit_t "header" to the bytes-buffer.
755  *
756  *              Fields will be packed into the buffer in a predictable manner,
757  *              any numbers stored in "network" (Big-Endian) word order.
758  *
759  *              The programmer must ensure that the destination buffer is
760  *              large enough to hold the expected data.
761  *
762  * Return:      The number of bytes written to the buffer.
763  * ---------------------------------------------------------------------------
764  */
765 size_t
H5FD_mirror_xmit_encode_header(unsigned char * dest,const H5FD_mirror_xmit_t * x)766 H5FD_mirror_xmit_encode_header(unsigned char *dest, const H5FD_mirror_xmit_t *x)
767 {
768     size_t n_writ = 0;
769 
770     LOG_OP_CALL(__func__);
771 
772     HDassert(dest && x);
773 
774     n_writ += H5FD__mirror_xmit_encode_uint32((dest + n_writ), x->magic);
775     n_writ += H5FD__mirror_xmit_encode_uint8((dest + n_writ), x->version);
776     n_writ += H5FD__mirror_xmit_encode_uint32((dest + n_writ), x->session_token);
777     n_writ += H5FD__mirror_xmit_encode_uint32((dest + n_writ), x->xmit_count);
778     n_writ += H5FD__mirror_xmit_encode_uint8((dest + n_writ), x->op);
779     HDassert(n_writ == H5FD_MIRROR_XMIT_HEADER_SIZE);
780 
781     return n_writ;
782 } /* end H5FD_mirror_xmit_encode_header() */
783 
784 /* ---------------------------------------------------------------------------
785  * Function:    H5FD_mirror_xmit_encode_lock
786  *
787  * Purpose:     Encode a mirror_xmit_lock_t to the bytes-buffer.
788  *              Fields will be packed into the buffer in a predictable manner,
789  *              any numbers stored in "network" (Big-Endian) word order.
790  *
791  *              The programmer must ensure that the destination buffer is
792  *              large enough to hold the expected data.
793  *
794  * Return:      The number of bytes written to the buffer.
795  * ---------------------------------------------------------------------------
796  */
797 size_t
H5FD_mirror_xmit_encode_lock(unsigned char * dest,const H5FD_mirror_xmit_lock_t * x)798 H5FD_mirror_xmit_encode_lock(unsigned char *dest, const H5FD_mirror_xmit_lock_t *x)
799 {
800     size_t n_writ = 0;
801 
802     LOG_OP_CALL(__func__);
803 
804     HDassert(dest && x);
805 
806     n_writ += H5FD_mirror_xmit_encode_header(dest, (const H5FD_mirror_xmit_t *)&(x->pub));
807     n_writ += H5FD__mirror_xmit_encode_uint64(&dest[n_writ], x->rw);
808     HDassert(n_writ == H5FD_MIRROR_XMIT_LOCK_SIZE);
809 
810     return n_writ;
811 } /* end H5FD_mirror_xmit_encode_lock() */
812 
813 /* ---------------------------------------------------------------------------
814  * Function:    H5FD_mirror_xmit_encode_open
815  *
816  * Purpose:     Encode a mirror_xmit_open_t to the bytes-buffer.
817  *              Fields will be packed into the buffer in a predictable manner,
818  *              any numbers stored in "network" (Big-Endian) word order.
819  *
820  *              The programmer must ensure that the destination buffer is
821  *              large enough to hold the expected data.
822  *
823  * Return:      The maximum number of bytes that this decoding operation might
824  *              have written into the buffer.
825  * ---------------------------------------------------------------------------
826  */
827 size_t
H5FD_mirror_xmit_encode_open(unsigned char * dest,const H5FD_mirror_xmit_open_t * x)828 H5FD_mirror_xmit_encode_open(unsigned char *dest, const H5FD_mirror_xmit_open_t *x)
829 {
830     size_t n_writ = 0;
831 
832     LOG_OP_CALL(__func__);
833 
834     HDassert(dest && x);
835 
836     /* clear entire structure, but especially its filepath string area */
837     HDmemset(dest, 0, H5FD_MIRROR_XMIT_OPEN_SIZE);
838 
839     n_writ += H5FD_mirror_xmit_encode_header(dest, (const H5FD_mirror_xmit_t *)&(x->pub));
840     n_writ += H5FD__mirror_xmit_encode_uint32(&dest[n_writ], x->flags);
841     n_writ += H5FD__mirror_xmit_encode_uint64(&dest[n_writ], x->maxaddr);
842     n_writ += H5FD__mirror_xmit_encode_uint64(&dest[n_writ], x->size_t_blob);
843     HDassert((H5FD_MIRROR_XMIT_OPEN_SIZE - H5FD_MIRROR_XMIT_FILEPATH_MAX) == n_writ);
844     HDstrncpy((char *)&dest[n_writ], x->filename, H5FD_MIRROR_XMIT_FILEPATH_MAX);
845 
846     return H5FD_MIRROR_XMIT_OPEN_SIZE;
847 } /* end H5FD_mirror_xmit_encode_open() */
848 
849 /* ---------------------------------------------------------------------------
850  * Function:    H5FD_mirror_xmit_encode_reply
851  *
852  * Purpose:     Encode a mirror_xmit_reply_t to the bytes-buffer.
853  *
854  *              Fields will be packed into the buffer in a predictable manner,
855  *              any numbers stored in "network" (Big-Endian) word order.
856  *
857  *              The programmer must ensure that the destination buffer is
858  *              large enough to hold the expected data.
859  *
860  * Return:      The maximum number of bytes that this decoding operation might
861  *              have written into the buffer.
862  * ---------------------------------------------------------------------------
863  */
864 size_t
H5FD_mirror_xmit_encode_reply(unsigned char * dest,const H5FD_mirror_xmit_reply_t * x)865 H5FD_mirror_xmit_encode_reply(unsigned char *dest, const H5FD_mirror_xmit_reply_t *x)
866 {
867     size_t n_writ = 0;
868 
869     LOG_OP_CALL(__func__);
870 
871     HDassert(dest && x);
872 
873     /* clear entire structure, but especially its message string area */
874     HDmemset(dest, 0, H5FD_MIRROR_XMIT_REPLY_SIZE);
875 
876     n_writ += H5FD_mirror_xmit_encode_header(dest, (const H5FD_mirror_xmit_t *)&(x->pub));
877     n_writ += H5FD__mirror_xmit_encode_uint32(&dest[n_writ], x->status);
878     HDassert((H5FD_MIRROR_XMIT_REPLY_SIZE - H5FD_MIRROR_STATUS_MESSAGE_MAX) == n_writ);
879     HDstrncpy((char *)&dest[n_writ], x->message, H5FD_MIRROR_STATUS_MESSAGE_MAX);
880 
881     return H5FD_MIRROR_XMIT_REPLY_SIZE;
882 } /* end H5FD_mirror_xmit_encode_reply() */
883 
884 /* ---------------------------------------------------------------------------
885  * Function:    H5FD_mirror_xmit_encode_set_eoa
886  *
887  * Purpose:     Encode a mirror_xmit_eoa_t to the bytes-buffer.
888  *
889  *              Fields will be packed into the buffer in a predictable manner,
890  *              any numbers stored in "network" (Big-Endian) word order.
891  *
892  *              The programmer must ensure that the destination buffer is
893  *              large enough to hold the expected data.
894  *
895  * Return:      The number of bytes written to the buffer.
896  * ---------------------------------------------------------------------------
897  */
898 size_t
H5FD_mirror_xmit_encode_set_eoa(unsigned char * dest,const H5FD_mirror_xmit_eoa_t * x)899 H5FD_mirror_xmit_encode_set_eoa(unsigned char *dest, const H5FD_mirror_xmit_eoa_t *x)
900 {
901     size_t n_writ = 0;
902 
903     LOG_OP_CALL(__func__);
904 
905     HDassert(dest && x);
906 
907     n_writ += H5FD_mirror_xmit_encode_header(dest, (const H5FD_mirror_xmit_t *)&(x->pub));
908     n_writ += H5FD__mirror_xmit_encode_uint8(&dest[n_writ], x->type);
909     n_writ += H5FD__mirror_xmit_encode_uint64(&dest[n_writ], x->eoa_addr);
910     HDassert(n_writ == H5FD_MIRROR_XMIT_EOA_SIZE);
911 
912     return n_writ;
913 } /* end H5FD_mirror_xmit_encode_set_eoa() */
914 
915 /* ---------------------------------------------------------------------------
916  * Function:    H5FD_mirror_xmit_encode_write
917  *
918  * Purpose:     Encode a mirror_xmit_write_t to the bytes-buffer.
919  *
920  *              Fields will be packed into the buffer in a predictable manner,
921  *              any numbers stored in "network" (Big-Endian) word order.
922  *
923  *              The programmer must ensure that the destination buffer is
924  *              large enough to hold the expected data.
925  *
926  * Return:      The number of bytes written to the buffer.
927  * ---------------------------------------------------------------------------
928  */
929 size_t
H5FD_mirror_xmit_encode_write(unsigned char * dest,const H5FD_mirror_xmit_write_t * x)930 H5FD_mirror_xmit_encode_write(unsigned char *dest, const H5FD_mirror_xmit_write_t *x)
931 {
932     size_t n_writ = 0;
933 
934     LOG_OP_CALL(__func__);
935 
936     HDassert(dest && x);
937 
938     n_writ += H5FD_mirror_xmit_encode_header(dest, (const H5FD_mirror_xmit_t *)&(x->pub));
939     n_writ += H5FD__mirror_xmit_encode_uint8(&dest[n_writ], x->type);
940     n_writ += H5FD__mirror_xmit_encode_uint64(&dest[n_writ], x->offset);
941     n_writ += H5FD__mirror_xmit_encode_uint64(&dest[n_writ], x->size);
942     HDassert(n_writ == H5FD_MIRROR_XMIT_WRITE_SIZE);
943 
944     return n_writ;
945 } /* end H5FD_mirror_xmit_encode_write() */
946 
947 /* ---------------------------------------------------------------------------
948  * Function:    H5FD_mirror_xmit_is_close
949  *
950  * Purpose:     Verify that a mirror_xmit_t is a valid CLOSE xmit.
951  *
952  *              Checks header validity and op code.
953  *
954  * Return:      TRUE if valid; else FALSE.
955  * ---------------------------------------------------------------------------
956  */
957 H5_ATTR_PURE hbool_t
H5FD_mirror_xmit_is_close(const H5FD_mirror_xmit_t * xmit)958 H5FD_mirror_xmit_is_close(const H5FD_mirror_xmit_t *xmit)
959 {
960     LOG_OP_CALL(__func__);
961 
962     HDassert(xmit);
963 
964     if ((TRUE == H5FD_mirror_xmit_is_xmit(xmit)) && (H5FD_MIRROR_OP_CLOSE == xmit->op))
965         return TRUE;
966 
967     return FALSE;
968 } /* end H5FD_mirror_xmit_is_close() */
969 
970 /* ---------------------------------------------------------------------------
971  * Function:    H5FD_mirror_xmit_is_lock
972  *
973  * Purpose:     Verify that a mirror_xmit_lock_t is a valid LOCK xmit.
974  *
975  *              Checks header validity and op code.
976  *
977  * Return:      TRUE if valid; else FALSE.
978  * ---------------------------------------------------------------------------
979  */
980 H5_ATTR_PURE hbool_t
H5FD_mirror_xmit_is_lock(const H5FD_mirror_xmit_lock_t * xmit)981 H5FD_mirror_xmit_is_lock(const H5FD_mirror_xmit_lock_t *xmit)
982 {
983     LOG_OP_CALL(__func__);
984 
985     HDassert(xmit);
986 
987     if ((TRUE == H5FD_mirror_xmit_is_xmit(&(xmit->pub))) && (H5FD_MIRROR_OP_LOCK == xmit->pub.op))
988         return TRUE;
989 
990     return FALSE;
991 } /* end H5FD_mirror_xmit_is_lock() */
992 
993 /* ---------------------------------------------------------------------------
994  * Function:    H5FD_mirror_xmit_is_open
995  *
996  * Purpose:     Verify that a mirror_xmit_open_t is a valid OPEN xmit.
997  *
998  *              Checks header validity and op code.
999  *
1000  * Return:      TRUE if valid; else FALSE.
1001  * ---------------------------------------------------------------------------
1002  */
1003 H5_ATTR_PURE hbool_t
H5FD_mirror_xmit_is_open(const H5FD_mirror_xmit_open_t * xmit)1004 H5FD_mirror_xmit_is_open(const H5FD_mirror_xmit_open_t *xmit)
1005 {
1006     LOG_OP_CALL(__func__);
1007 
1008     HDassert(xmit);
1009 
1010     if ((TRUE == H5FD_mirror_xmit_is_xmit(&(xmit->pub))) && (H5FD_MIRROR_OP_OPEN == xmit->pub.op))
1011 
1012         return TRUE;
1013 
1014     return FALSE;
1015 } /* end H5FD_mirror_xmit_is_open() */
1016 
1017 /* ---------------------------------------------------------------------------
1018  * Function:    H5FD_mirror_xmit_is_eoa
1019  *
1020  * Purpose:     Verify that a mirror_xmit_eoa_t is a valid SET-EOA xmit.
1021  *
1022  *              Checks header validity and op code.
1023  *
1024  * Return:      TRUE if valid; else FALSE.
1025  * ---------------------------------------------------------------------------
1026  */
1027 H5_ATTR_PURE hbool_t
H5FD_mirror_xmit_is_set_eoa(const H5FD_mirror_xmit_eoa_t * xmit)1028 H5FD_mirror_xmit_is_set_eoa(const H5FD_mirror_xmit_eoa_t *xmit)
1029 {
1030     LOG_OP_CALL(__func__);
1031 
1032     HDassert(xmit);
1033 
1034     if ((TRUE == H5FD_mirror_xmit_is_xmit(&(xmit->pub))) && (H5FD_MIRROR_OP_SET_EOA == xmit->pub.op))
1035         return TRUE;
1036 
1037     return FALSE;
1038 } /* end H5FD_mirror_xmit_is_eoa() */
1039 
1040 /* ---------------------------------------------------------------------------
1041  * Function:    H5FD_mirror_xmit_is_reply
1042  *
1043  * Purpose:     Verify that a mirror_xmit_reply_t is a valid REPLY xmit.
1044  *
1045  *              Checks header validity and op code.
1046  *
1047  * Return:      TRUE if valid; else FALSE.
1048  * ---------------------------------------------------------------------------
1049  */
1050 H5_ATTR_PURE hbool_t
H5FD_mirror_xmit_is_reply(const H5FD_mirror_xmit_reply_t * xmit)1051 H5FD_mirror_xmit_is_reply(const H5FD_mirror_xmit_reply_t *xmit)
1052 {
1053     LOG_OP_CALL(__func__);
1054 
1055     HDassert(xmit);
1056 
1057     if ((TRUE == H5FD_mirror_xmit_is_xmit(&(xmit->pub))) && (H5FD_MIRROR_OP_REPLY == xmit->pub.op))
1058         return TRUE;
1059 
1060     return FALSE;
1061 } /* end H5FD_mirror_xmit_is_reply() */
1062 
1063 /* ---------------------------------------------------------------------------
1064  * Function:    H5FD_mirror_xmit_is_write
1065  *
1066  * Purpose:     Verify that a mirror_xmit_write_t is a valid WRITE xmit.
1067  *
1068  *              Checks header validity and op code.
1069  *
1070  * Return:      TRUE if valid; else FALSE.
1071  * ---------------------------------------------------------------------------
1072  */
1073 H5_ATTR_PURE hbool_t
H5FD_mirror_xmit_is_write(const H5FD_mirror_xmit_write_t * xmit)1074 H5FD_mirror_xmit_is_write(const H5FD_mirror_xmit_write_t *xmit)
1075 {
1076     LOG_OP_CALL(__func__);
1077 
1078     HDassert(xmit);
1079 
1080     if ((TRUE == H5FD_mirror_xmit_is_xmit(&(xmit->pub))) && (H5FD_MIRROR_OP_WRITE == xmit->pub.op))
1081         return TRUE;
1082 
1083     return FALSE;
1084 } /* end H5FD_mirror_xmit_is_write() */
1085 
1086 /* ---------------------------------------------------------------------------
1087  * Function:    H5FD_mirror_xmit_is_xmit
1088  *
1089  * Purpose:     Verify that a mirror_xmit_t is well-formed.
1090  *
1091  *              Checks magic number and structure version.
1092  *
1093  * Return:      TRUE if valid; else FALSE.
1094  * ---------------------------------------------------------------------------
1095  */
1096 H5_ATTR_PURE hbool_t
H5FD_mirror_xmit_is_xmit(const H5FD_mirror_xmit_t * xmit)1097 H5FD_mirror_xmit_is_xmit(const H5FD_mirror_xmit_t *xmit)
1098 {
1099     LOG_OP_CALL(__func__);
1100 
1101     HDassert(xmit);
1102 
1103     if ((H5FD_MIRROR_XMIT_MAGIC != xmit->magic) || (H5FD_MIRROR_XMIT_CURR_VERSION != xmit->version))
1104         return FALSE;
1105 
1106     return TRUE;
1107 } /* end H5FD_mirror_xmit_is_xmit() */
1108 
1109 /* ----------------------------------------------------------------------------
1110  * Function:    H5FD__mirror_verify_reply
1111  *
1112  * Purpose:     Wait for and read reply data from remote processes.
1113  *              Sanity-check that a reply is well-formed and valid.
1114  *              If all checks pass, inspect the reply contents and handle
1115  *              reported error, if not an OK reply.
1116  *
1117  * Return:      SUCCEED if ok, else FAIL.
1118  * ----------------------------------------------------------------------------
1119  */
1120 static herr_t
H5FD__mirror_verify_reply(H5FD_mirror_t * file)1121 H5FD__mirror_verify_reply(H5FD_mirror_t *file)
1122 {
1123     unsigned char *                 xmit_buf = NULL;
1124     struct H5FD_mirror_xmit_reply_t reply;
1125     ssize_t                         read_ret  = 0;
1126     herr_t                          ret_value = SUCCEED;
1127 
1128     FUNC_ENTER_STATIC
1129 
1130     LOG_OP_CALL(FUNC);
1131 
1132     HDassert(file && file->sock_fd);
1133 
1134     xmit_buf = H5FL_BLK_MALLOC(xmit, H5FD_MIRROR_XMIT_BUFFER_MAX);
1135     if (NULL == xmit_buf)
1136         HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, FAIL, "unable to allocate xmit buffer");
1137 
1138     read_ret = HDread(file->sock_fd, xmit_buf, H5FD_MIRROR_XMIT_REPLY_SIZE);
1139     if (read_ret < 0)
1140         HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "unable to read reply");
1141     if (read_ret != H5FD_MIRROR_XMIT_REPLY_SIZE)
1142         HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "unexpected read size");
1143 
1144     LOG_XMIT_BYTES("reply", xmit_buf, read_ret);
1145 
1146     if (H5FD_mirror_xmit_decode_reply(&reply, xmit_buf) != H5FD_MIRROR_XMIT_REPLY_SIZE)
1147         HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "unable to decode reply xmit");
1148 
1149     if (H5FD_mirror_xmit_is_reply(&reply) != TRUE)
1150         HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "xmit op code was not REPLY");
1151 
1152     if (reply.pub.session_token != file->xmit.session_token)
1153         HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "wrong session");
1154     if (reply.pub.xmit_count != (file->xmit_i)++)
1155         HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "xmit out of sync");
1156     if (reply.status != H5FD_MIRROR_STATUS_OK)
1157         HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "%s", (const char *)(reply.message));
1158 
1159 done:
1160     if (xmit_buf)
1161         xmit_buf = H5FL_BLK_FREE(xmit, xmit_buf);
1162 
1163     FUNC_LEAVE_NOAPI(ret_value);
1164 } /* end H5FD__mirror_verify_reply() */
1165 
1166 /* -------------------------------------------------------------------------
1167  * Function:    H5FD__mirror_fapl_get
1168  *
1169  * Purpose:     Get the file access propety list which could be used to create
1170  *              an identical file.
1171  *
1172  * Return:      Success: pointer to the new file access property list value.
1173  *              Failure: NULL
1174  * -------------------------------------------------------------------------
1175  */
1176 static void *
H5FD__mirror_fapl_get(H5FD_t * _file)1177 H5FD__mirror_fapl_get(H5FD_t *_file)
1178 {
1179     H5FD_mirror_t *     file      = (H5FD_mirror_t *)_file;
1180     H5FD_mirror_fapl_t *fa        = NULL;
1181     void *              ret_value = NULL;
1182 
1183     FUNC_ENTER_STATIC
1184 
1185     LOG_OP_CALL(FUNC);
1186 
1187     fa = (H5FD_mirror_fapl_t *)H5MM_calloc(sizeof(H5FD_mirror_fapl_t));
1188     if (NULL == fa)
1189         HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, NULL, "calloc failed");
1190 
1191     H5MM_memcpy(fa, &(file->fa), sizeof(H5FD_mirror_fapl_t));
1192 
1193     ret_value = fa;
1194 
1195 done:
1196     if (ret_value == NULL)
1197         if (fa != NULL)
1198             H5MM_xfree(fa);
1199 
1200     FUNC_LEAVE_NOAPI(ret_value)
1201 } /* end H5FD__mirror_fapl_get() */
1202 
1203 /* -------------------------------------------------------------------------
1204  * Function:    H5FD__mirror_fapl_copy
1205  *
1206  * Purpose:     Copies the mirror vfd-specific file access properties.
1207  *
1208  * Return:      Success:        Pointer to a new property list
1209  *              Failure:        NULL
1210  * -------------------------------------------------------------------------
1211  */
1212 static void *
H5FD__mirror_fapl_copy(const void * _old_fa)1213 H5FD__mirror_fapl_copy(const void *_old_fa)
1214 {
1215     const H5FD_mirror_fapl_t *old_fa    = (const H5FD_mirror_fapl_t *)_old_fa;
1216     H5FD_mirror_fapl_t *      new_fa    = NULL;
1217     void *                    ret_value = NULL;
1218 
1219     FUNC_ENTER_STATIC
1220 
1221     LOG_OP_CALL(FUNC);
1222 
1223     new_fa = (H5FD_mirror_fapl_t *)H5MM_malloc(sizeof(H5FD_mirror_fapl_t));
1224     if (new_fa == NULL)
1225         HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, NULL, "memory allocation failed");
1226 
1227     H5MM_memcpy(new_fa, old_fa, sizeof(H5FD_mirror_fapl_t));
1228     ret_value = new_fa;
1229 
1230 done:
1231     if (ret_value == NULL)
1232         if (new_fa != NULL)
1233             H5MM_xfree(new_fa);
1234 
1235     FUNC_LEAVE_NOAPI(ret_value)
1236 } /* end H5FD__mirror_fapl_copy() */
1237 
1238 /*-------------------------------------------------------------------------
1239  * Function:    H5FD__mirror_fapl_free
1240  *
1241  * Purpose:     Frees the mirror VFD-specific file access properties.
1242  *
1243  * Return:      SUCCEED (cannot fail)
1244  *-------------------------------------------------------------------------
1245  */
1246 static herr_t
H5FD__mirror_fapl_free(void * _fa)1247 H5FD__mirror_fapl_free(void *_fa)
1248 {
1249     H5FD_mirror_fapl_t *fa = (H5FD_mirror_fapl_t *)_fa;
1250 
1251     FUNC_ENTER_STATIC_NOERR
1252 
1253     LOG_OP_CALL(FUNC);
1254 
1255     /* sanity check */
1256     HDassert(fa != NULL);
1257     HDassert(fa->magic == H5FD_MIRROR_FAPL_MAGIC);
1258 
1259     fa->magic += 1; /* invalidate */
1260     H5MM_xfree(fa);
1261 
1262     FUNC_LEAVE_NOAPI(SUCCEED)
1263 } /* end H5FD__mirror_fapl_free() */
1264 
1265 /* -------------------------------------------------------------------------
1266  * Function:    H5Pget_fapl_mirror
1267  *
1268  * Purpose:     Get the configuration information for this fapl.
1269  *              Data is memcopied into the fa_dst pointer.
1270  *
1271  * Return:      SUCCEED/FAIL
1272  * -------------------------------------------------------------------------
1273  */
1274 herr_t
H5Pget_fapl_mirror(hid_t fapl_id,H5FD_mirror_fapl_t * fa_dst)1275 H5Pget_fapl_mirror(hid_t fapl_id, H5FD_mirror_fapl_t *fa_dst)
1276 {
1277     const H5FD_mirror_fapl_t *fa_src    = NULL;
1278     H5P_genplist_t *          plist     = NULL;
1279     herr_t                    ret_value = SUCCEED;
1280 
1281     FUNC_ENTER_API(FAIL)
1282     H5TRACE2("e", "i*x", fapl_id, fa_dst);
1283 
1284     LOG_OP_CALL(FUNC);
1285 
1286     if (NULL == fa_dst)
1287         HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "fa_dst is NULL");
1288 
1289     plist = H5P_object_verify(fapl_id, H5P_FILE_ACCESS);
1290     if (NULL == plist)
1291         HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list");
1292     if (H5P_peek_driver(plist) != H5FD_MIRROR)
1293         HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "incorrect VFL driver");
1294 
1295     fa_src = (const H5FD_mirror_fapl_t *)H5P_peek_driver_info(plist);
1296     if (NULL == fa_src)
1297         HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "bad VFL driver info");
1298 
1299     HDassert(fa_src->magic == H5FD_MIRROR_FAPL_MAGIC); /* sanity check */
1300 
1301     H5MM_memcpy(fa_dst, fa_src, sizeof(H5FD_mirror_fapl_t));
1302 
1303 done:
1304     FUNC_LEAVE_API(ret_value);
1305 } /* end H5Pget_fapl_mirror() */
1306 
1307 /*-------------------------------------------------------------------------
1308  * Function:    H5Pset_fapl_mirror
1309  *
1310  * Purpose:     Modify the file access property list to use the mirror
1311  *              driver (H5FD_MIRROR) defined in this source file.
1312  *
1313  * Return:      SUCCEED/FAIL
1314  *-------------------------------------------------------------------------
1315  */
1316 herr_t
H5Pset_fapl_mirror(hid_t fapl_id,H5FD_mirror_fapl_t * fa)1317 H5Pset_fapl_mirror(hid_t fapl_id, H5FD_mirror_fapl_t *fa)
1318 {
1319     H5P_genplist_t *plist     = NULL;
1320     herr_t          ret_value = FAIL;
1321 
1322     FUNC_ENTER_API(FAIL)
1323     H5TRACE2("e", "i*x", fapl_id, fa);
1324 
1325     LOG_OP_CALL(FUNC);
1326 
1327     plist = H5P_object_verify(fapl_id, H5P_FILE_ACCESS);
1328     if (NULL == plist)
1329         HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list");
1330     if (NULL == fa)
1331         HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "null fapl_t pointer");
1332     if (H5FD_MIRROR_FAPL_MAGIC != fa->magic)
1333         HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid fapl_t magic");
1334     if (H5FD_MIRROR_CURR_FAPL_T_VERSION != fa->version)
1335         HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unknown fapl_t version");
1336 
1337     ret_value = H5P_set_driver(plist, H5FD_MIRROR, (const void *)fa);
1338 
1339 done:
1340     FUNC_LEAVE_API(ret_value)
1341 } /* end H5Pset_fapl_mirror() */
1342 
1343 /*-------------------------------------------------------------------------
1344  * Function:    H5FD__mirror_open
1345  *
1346  * Purpose:     Create and/or opens a file as an HDF5 file.
1347  *
1348  *              Initiate connection with remote Server/Writer.
1349  *              If successful, the remote file is open.
1350  *
1351  * Return:      Success:    A pointer to a new file data structure. The
1352  *                          public fields will be initialized by the
1353  *                          caller, which is always H5FD_open().
1354  *              Failure:    NULL
1355  *-------------------------------------------------------------------------
1356  */
1357 static H5FD_t *
H5FD__mirror_open(const char * name,unsigned flags,hid_t fapl_id,haddr_t maxaddr)1358 H5FD__mirror_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr)
1359 {
1360     int                      live_socket = -1;
1361     struct sockaddr_in       target_addr;
1362     socklen_t                addr_size;
1363     unsigned char *          xmit_buf = NULL;
1364     H5FD_mirror_fapl_t       fa;
1365     H5FD_mirror_t *          file      = NULL;
1366     H5FD_mirror_xmit_open_t *open_xmit = NULL;
1367     H5FD_t *                 ret_value = NULL;
1368 
1369     FUNC_ENTER_STATIC
1370 
1371     LOG_OP_CALL(FUNC);
1372 
1373     /* --------------- */
1374     /* Check arguments */
1375     /* --------------- */
1376 
1377     if (!name || !*name)
1378         HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "invalid file name");
1379     if (HDstrlen(name) >= H5FD_MIRROR_XMIT_FILEPATH_MAX)
1380         HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "filename is too long");
1381     if (0 == maxaddr || HADDR_UNDEF == maxaddr)
1382         HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, NULL, "bogus maxaddr");
1383     if (ADDR_OVERFLOW(maxaddr))
1384         HGOTO_ERROR(H5E_ARGS, H5E_OVERFLOW, NULL, "bogus maxaddr");
1385 
1386     if (H5Pget_fapl_mirror(fapl_id, &fa) == FAIL)
1387         HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "can't get config info");
1388     if (H5FD_MIRROR_FAPL_MAGIC != fa.magic)
1389         HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "invalid fapl magic");
1390     if (H5FD_MIRROR_CURR_FAPL_T_VERSION != fa.version)
1391         HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "invalid fapl version");
1392 
1393     /* --------------------- */
1394     /* Handshake with remote */
1395     /* --------------------- */
1396 
1397     live_socket = HDsocket(AF_INET, SOCK_STREAM, 0);
1398     if (live_socket < 0)
1399         HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "can't create socket");
1400 
1401     target_addr.sin_family      = AF_INET;
1402     target_addr.sin_port        = HDhtons((uint16_t)fa.handshake_port);
1403     target_addr.sin_addr.s_addr = HDinet_addr(fa.remote_ip);
1404     HDmemset(target_addr.sin_zero, '\0', sizeof target_addr.sin_zero);
1405 
1406     addr_size = sizeof(target_addr);
1407     if (HDconnect(live_socket, (struct sockaddr *)&target_addr, addr_size) < 0)
1408         HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "can't connect to remote server");
1409 
1410     /* ------------- */
1411     /* Open the file */
1412     /* ------------- */
1413 
1414     file = (H5FD_mirror_t *)H5FL_CALLOC(H5FD_mirror_t);
1415     if (NULL == file)
1416         HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, NULL, "unable to allocate file struct");
1417 
1418     file->sock_fd = live_socket;
1419     file->xmit_i  = 0;
1420 
1421     file->xmit.magic         = H5FD_MIRROR_XMIT_MAGIC;
1422     file->xmit.version       = H5FD_MIRROR_XMIT_CURR_VERSION;
1423     file->xmit.xmit_count    = file->xmit_i++;
1424     file->xmit.session_token = (uint32_t)(0x01020304 ^ file->sock_fd); /* TODO: hashing? */
1425     /* int --> uint32_t may truncate on some systems... shouldn't matter? */
1426 
1427     open_xmit = (H5FD_mirror_xmit_open_t *)H5FL_CALLOC(H5FD_mirror_xmit_open_t);
1428     if (NULL == open_xmit)
1429         HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, NULL, "unable to allocate open_xmit struct");
1430 
1431     file->xmit.op          = H5FD_MIRROR_OP_OPEN;
1432     open_xmit->pub         = file->xmit;
1433     open_xmit->flags       = (uint32_t)flags;
1434     open_xmit->maxaddr     = (uint64_t)maxaddr;
1435     open_xmit->size_t_blob = (uint64_t)((size_t)(-1));
1436     HDsnprintf(open_xmit->filename, H5FD_MIRROR_XMIT_FILEPATH_MAX - 1, "%s", name);
1437 
1438     xmit_buf = H5FL_BLK_MALLOC(xmit, H5FD_MIRROR_XMIT_BUFFER_MAX);
1439     if (NULL == xmit_buf)
1440         HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, NULL, "unable to allocate xmit buffer");
1441 
1442     if (H5FD_mirror_xmit_encode_open(xmit_buf, open_xmit) != H5FD_MIRROR_XMIT_OPEN_SIZE)
1443         HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, NULL, "unable to encode open");
1444 
1445     LOG_XMIT_BYTES("open", xmit_buf, H5FD_MIRROR_XMIT_OPEN_SIZE);
1446 
1447     if (HDwrite(file->sock_fd, xmit_buf, H5FD_MIRROR_XMIT_OPEN_SIZE) < 0)
1448         HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, NULL, "unable to transmit open");
1449 
1450     if (H5FD__mirror_verify_reply(file) == FAIL)
1451         HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, NULL, "invalid reply");
1452 
1453     ret_value = (H5FD_t *)file;
1454 
1455 done:
1456     if (NULL == ret_value) {
1457         if (file)
1458             file = H5FL_FREE(H5FD_mirror_t, file);
1459         if (live_socket >= 0 && HDclose(live_socket) < 0)
1460             HDONE_ERROR(H5E_VFL, H5E_CANTCLOSEFILE, NULL, "can't close socket");
1461     }
1462 
1463     if (open_xmit)
1464         open_xmit = H5FL_FREE(H5FD_mirror_xmit_open_t, open_xmit);
1465     if (xmit_buf)
1466         xmit_buf = H5FL_BLK_FREE(xmit, xmit_buf);
1467 
1468     FUNC_LEAVE_NOAPI(ret_value)
1469 } /* end H5FD__mirror_open() */
1470 
1471 /*-------------------------------------------------------------------------
1472  * Function:    H5FD__mirror_close
1473  *
1474  * Purpose:     Closes the HDF5 file.
1475  *
1476  *              Tries to send a CLOSE op to the remote Writer and expects
1477  *              a valid reply, then closes the socket.
1478  *              In error, attempts to send a deliberately invalid xmit to the
1479  *              Writer to get it to close/abort, then attempts to close the
1480  *              socket.
1481  *
1482  * Return:      Success:    SUCCEED
1483  *              Failure:    FAIL, file possibly not closed but resources freed.
1484  *-------------------------------------------------------------------------
1485  */
1486 static herr_t
H5FD__mirror_close(H5FD_t * _file)1487 H5FD__mirror_close(H5FD_t *_file)
1488 {
1489     H5FD_mirror_t *file         = (H5FD_mirror_t *)_file;
1490     unsigned char *xmit_buf     = NULL;
1491     int            xmit_encoded = 0; /* monitor point of failure */
1492     herr_t         ret_value    = SUCCEED;
1493 
1494     FUNC_ENTER_STATIC
1495 
1496     LOG_OP_CALL(FUNC);
1497 
1498     /* Sanity check */
1499     HDassert(file);
1500     HDassert(file->sock_fd >= 0);
1501 
1502     file->xmit.xmit_count = (file->xmit_i)++;
1503     file->xmit.op         = H5FD_MIRROR_OP_CLOSE;
1504 
1505     xmit_buf = H5FL_BLK_MALLOC(xmit, H5FD_MIRROR_XMIT_BUFFER_MAX);
1506     if (NULL == xmit_buf)
1507         HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, FAIL, "unable to allocate xmit buffer");
1508 
1509     if (H5FD_mirror_xmit_encode_header(xmit_buf, &(file->xmit)) != H5FD_MIRROR_XMIT_HEADER_SIZE)
1510         HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to encode close");
1511     xmit_encoded = 1;
1512 
1513     LOG_XMIT_BYTES("close", xmit_buf, H5FD_MIRROR_XMIT_HEADER_SIZE);
1514 
1515     if (HDwrite(file->sock_fd, xmit_buf, H5FD_MIRROR_XMIT_HEADER_SIZE) < 0)
1516         HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to transmit close");
1517 
1518     if (H5FD__mirror_verify_reply(file) == FAIL)
1519         HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "invalid reply");
1520 
1521     if (HDclose(file->sock_fd) < 0)
1522         HGOTO_ERROR(H5E_VFL, H5E_CANTCLOSEFILE, FAIL, "can't close socket");
1523 
1524 done:
1525     if (ret_value == FAIL) {
1526         if (xmit_encoded == 0) {
1527             /* Encode failed; send GOODBYE to force writer halt.
1528              * We can ignore any response from the writer, if we receive
1529              * any reply at all.
1530              */
1531             if (HDwrite(file->sock_fd, "GOODBYE", HDstrlen("GOODBYE")) < 0) {
1532                 HDONE_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to transmit close");
1533                 if (HDclose(file->sock_fd) < 0)
1534                     HDONE_ERROR(H5E_VFL, H5E_CANTCLOSEFILE, FAIL, "can't close socket");
1535                 file->sock_fd = -1; /* invalidate for later */
1536             }                       /* end if problem writing goodbye; go down hard */
1537             else if (HDshutdown(file->sock_fd, SHUT_WR) < 0)
1538                 HDONE_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "can't shutdown socket write: %s",
1539                             HDstrerror(errno));
1540         } /* end if xmit encode failed */
1541 
1542         if (file->sock_fd >= 0)
1543             if (HDclose(file->sock_fd) < 0)
1544                 HDONE_ERROR(H5E_VFL, H5E_CANTCLOSEFILE, FAIL, "can't close socket");
1545     } /* end if error */
1546 
1547     file = H5FL_FREE(H5FD_mirror_t, file); /* always release resources */
1548 
1549     if (xmit_buf)
1550         xmit_buf = H5FL_BLK_FREE(xmit, xmit_buf);
1551 
1552     FUNC_LEAVE_NOAPI(ret_value)
1553 } /* end H5FD__mirror_close() */
1554 
1555 /*-------------------------------------------------------------------------
1556  * Function:    H5FD__mirror_query
1557  *
1558  * Purpose:     Get the driver feature flags implemented by the driver.
1559  *
1560  * Return:      SUCCEED (non-negative) (can't fail)
1561  *-------------------------------------------------------------------------
1562  */
1563 static herr_t
H5FD__mirror_query(const H5FD_t H5_ATTR_UNUSED * _file,unsigned long * flags)1564 H5FD__mirror_query(const H5FD_t H5_ATTR_UNUSED *_file, unsigned long *flags)
1565 {
1566     FUNC_ENTER_STATIC_NOERR;
1567 
1568     LOG_OP_CALL(FUNC);
1569 
1570     /* Notice: the Mirror VFD Writer currently uses only the Sec2 driver as
1571      * the underying driver -- as such, the Mirror VFD implementation copies
1572      * the Sec2 feature flags as its own.
1573      *
1574      * File pointer is always NULL/unused -- the H5FD_FEAT_IGNORE_DRVRINFO flag
1575      * is never included.
1576      * -- JOS 2020-01-13
1577      */
1578     if (flags)
1579         *flags = H5FD_FEAT_AGGREGATE_METADATA | H5FD_FEAT_ACCUMULATE_METADATA | H5FD_FEAT_DATA_SIEVE |
1580                  H5FD_FEAT_AGGREGATE_SMALLDATA | H5FD_FEAT_POSIX_COMPAT_HANDLE | H5FD_FEAT_SUPPORTS_SWMR_IO |
1581                  H5FD_FEAT_DEFAULT_VFD_COMPATIBLE;
1582 
1583     FUNC_LEAVE_NOAPI(SUCCEED);
1584 } /* end H5FD__mirror_query() */
1585 
1586 /*-------------------------------------------------------------------------
1587  * Function:    H5FD__mirror_get_eoa
1588  *
1589  * Purpose:     Gets the end-of-address marker for the file. The EOA marker
1590  *              is the first address past the last byte allocated in the
1591  *              format address space.
1592  *
1593  *              Required to register the driver.
1594  *
1595  * Return:      The end-of-address marker.
1596  *-------------------------------------------------------------------------
1597  */
1598 static haddr_t
H5FD__mirror_get_eoa(const H5FD_t * _file,H5FD_mem_t H5_ATTR_UNUSED type)1599 H5FD__mirror_get_eoa(const H5FD_t *_file, H5FD_mem_t H5_ATTR_UNUSED type)
1600 {
1601     const H5FD_mirror_t *file = (const H5FD_mirror_t *)_file;
1602 
1603     FUNC_ENTER_STATIC_NOERR
1604 
1605     LOG_OP_CALL(FUNC);
1606 
1607     HDassert(file);
1608 
1609     FUNC_LEAVE_NOAPI(file->eoa)
1610 } /* end H5FD__mirror_get_eoa() */
1611 
1612 /*-------------------------------------------------------------------------
1613  * Function:    H5FD__mirror_set_eoa
1614  *
1615  * Purpose:     Set the end-of-address marker for the file. This function is
1616  *              called shortly after an existing HDF5 file is opened in order
1617  *              to tell the driver where the end of the HDF5 data is located.
1618  *
1619  * Return:      SUCCEED / FAIL
1620  *-------------------------------------------------------------------------
1621  */
1622 static herr_t
H5FD__mirror_set_eoa(H5FD_t * _file,H5FD_mem_t type,haddr_t addr)1623 H5FD__mirror_set_eoa(H5FD_t *_file, H5FD_mem_t type, haddr_t addr)
1624 {
1625     H5FD_mirror_xmit_eoa_t xmit_eoa;
1626     unsigned char *        xmit_buf  = NULL;
1627     H5FD_mirror_t *        file      = (H5FD_mirror_t *)_file;
1628     herr_t                 ret_value = SUCCEED;
1629 
1630     FUNC_ENTER_STATIC
1631 
1632     LOG_OP_CALL(FUNC);
1633 
1634     HDassert(file);
1635 
1636     file->eoa = addr; /* local copy */
1637 
1638     file->xmit.xmit_count = (file->xmit_i)++;
1639     file->xmit.op         = H5FD_MIRROR_OP_SET_EOA;
1640 
1641     xmit_eoa.pub      = file->xmit;
1642     xmit_eoa.type     = (uint8_t)type;
1643     xmit_eoa.eoa_addr = (uint64_t)addr;
1644 
1645     xmit_buf = H5FL_BLK_MALLOC(xmit, H5FD_MIRROR_XMIT_BUFFER_MAX);
1646     if (NULL == xmit_buf)
1647         HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, FAIL, "unable to allocate xmit buffer");
1648 
1649     if (H5FD_mirror_xmit_encode_set_eoa(xmit_buf, &xmit_eoa) != H5FD_MIRROR_XMIT_EOA_SIZE)
1650         HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "unable to encode set-eoa");
1651 
1652     LOG_XMIT_BYTES("set-eoa", xmit_buf, H5FD_MIRROR_XMIT_EOA_SIZE);
1653 
1654     if (HDwrite(file->sock_fd, xmit_buf, H5FD_MIRROR_XMIT_EOA_SIZE) < 0)
1655         HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "unable to transmit set-eoa");
1656 
1657     if (H5FD__mirror_verify_reply(file) == FAIL)
1658         HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "invalid reply");
1659 
1660 done:
1661     if (xmit_buf)
1662         xmit_buf = H5FL_BLK_FREE(xmit, xmit_buf);
1663 
1664     FUNC_LEAVE_NOAPI(ret_value)
1665 } /* end H5FD__mirror_set_eoa() */
1666 
1667 /*-------------------------------------------------------------------------
1668  * Function:    H5FD__mirror_get_eof
1669  *
1670  * Purpose:     Returns the end-of-file marker, which is the greater of
1671  *              either the filesystem end-of-file or the HDF5 end-of-address
1672  *              markers.
1673  *
1674  *              Required to register the driver.
1675  *
1676  * Return:      End of file address, the first address past the end of the
1677  *              "file", either the filesystem file or the HDF5 file.
1678  *-------------------------------------------------------------------------
1679  */
1680 static haddr_t
H5FD__mirror_get_eof(const H5FD_t * _file,H5FD_mem_t H5_ATTR_UNUSED type)1681 H5FD__mirror_get_eof(const H5FD_t *_file, H5FD_mem_t H5_ATTR_UNUSED type)
1682 {
1683     const H5FD_mirror_t *file = (const H5FD_mirror_t *)_file;
1684 
1685     FUNC_ENTER_STATIC_NOERR
1686 
1687     LOG_OP_CALL(FUNC);
1688 
1689     HDassert(file);
1690 
1691     FUNC_LEAVE_NOAPI(file->eof)
1692 } /* end H5FD__mirror_get_eof() */
1693 
1694 /*-------------------------------------------------------------------------
1695  * Function:    H5FD__mirror_read
1696  *
1697  * Purpose:     Required to register the driver, but if called, MUST fail.
1698  *
1699  * Return:      FAIL
1700  *-------------------------------------------------------------------------
1701  */
1702 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)1703 H5FD__mirror_read(H5FD_t H5_ATTR_UNUSED *_file, H5FD_mem_t H5_ATTR_UNUSED type, hid_t H5_ATTR_UNUSED fapl_id,
1704                   haddr_t H5_ATTR_UNUSED addr, size_t H5_ATTR_UNUSED size, void H5_ATTR_UNUSED *buf)
1705 {
1706     FUNC_ENTER_STATIC_NOERR
1707 
1708     LOG_OP_CALL(FUNC);
1709 
1710     FUNC_LEAVE_NOAPI(FAIL)
1711 } /* end H5FD__mirror_read() */
1712 
1713 /*-------------------------------------------------------------------------
1714  * Function:    H5FD__mirror_write
1715  *
1716  * Purpose:     Writes SIZE bytes of data to FILE beginning at address ADDR
1717  *              from buffer BUF according to data transfer properties in
1718  *              DXPL_ID.
1719  *
1720  *              Send metadata regarding the write (location, size) to the
1721  *              remote Writer, then separately transmits the data.
1722  *              Both transmission expect an OK reply from the Writer.
1723  *              This two-exchange approach incurs significant overhead,
1724  *              but is a simple and modular approach.
1725  *              Start optimizations here.
1726  *
1727  * Return:      SUCCEED/FAIL
1728  *-------------------------------------------------------------------------
1729  */
1730 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)1731 H5FD__mirror_write(H5FD_t *_file, H5FD_mem_t type, hid_t H5_ATTR_UNUSED dxpl_id, haddr_t addr, size_t size,
1732                    const void *buf)
1733 {
1734     H5FD_mirror_xmit_write_t xmit_write;
1735     unsigned char *          xmit_buf  = NULL;
1736     H5FD_mirror_t *          file      = (H5FD_mirror_t *)_file;
1737     herr_t                   ret_value = SUCCEED;
1738 
1739     FUNC_ENTER_STATIC
1740 
1741     LOG_OP_CALL(FUNC);
1742 
1743     HDassert(file);
1744     HDassert(buf);
1745 
1746     file->xmit.xmit_count = (file->xmit_i)++;
1747     file->xmit.op         = H5FD_MIRROR_OP_WRITE;
1748 
1749     xmit_write.pub    = file->xmit;
1750     xmit_write.size   = (uint64_t)size;
1751     xmit_write.offset = (uint64_t)addr;
1752     xmit_write.type   = (uint8_t)type;
1753 
1754     xmit_buf = H5FL_BLK_MALLOC(xmit, H5FD_MIRROR_XMIT_BUFFER_MAX);
1755     if (NULL == xmit_buf)
1756         HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, FAIL, "unable to allocate xmit buffer");
1757 
1758     /* Notify Writer of incoming data to write. */
1759     if (H5FD_mirror_xmit_encode_write(xmit_buf, &xmit_write) != H5FD_MIRROR_XMIT_WRITE_SIZE)
1760         HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "unable to encode write");
1761 
1762     LOG_XMIT_BYTES("write", xmit_buf, H5FD_MIRROR_XMIT_WRITE_SIZE);
1763 
1764     if (HDwrite(file->sock_fd, xmit_buf, H5FD_MIRROR_XMIT_WRITE_SIZE) < 0)
1765         HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "unable to transmit write");
1766 
1767     /* Check that our write xmission was received */
1768     if (H5FD__mirror_verify_reply(file) == FAIL)
1769         HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "invalid reply");
1770 
1771     /* Send the data to be written */
1772     if (HDwrite(file->sock_fd, buf, size) < 0)
1773         HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "unable to transmit data");
1774 
1775     /* Writer should reply that it got the data and is still okay/ready */
1776     if (H5FD__mirror_verify_reply(file) == FAIL)
1777         HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "invalid reply");
1778 
1779 done:
1780     if (xmit_buf)
1781         xmit_buf = H5FL_BLK_FREE(xmit, xmit_buf);
1782 
1783     FUNC_LEAVE_NOAPI(ret_value)
1784 } /* end H5FD__mirror_write() */
1785 
1786 /*-------------------------------------------------------------------------
1787  * Function:    H5FD__mirror_truncate
1788  *
1789  * Purpose:     Makes sure that the true file size is the same (or larger)
1790  *              than the end-of-address.
1791  *
1792  * Return:      SUCCEED/FAIL
1793  *-------------------------------------------------------------------------
1794  */
1795 static herr_t
H5FD__mirror_truncate(H5FD_t * _file,hid_t H5_ATTR_UNUSED dxpl_id,hbool_t H5_ATTR_UNUSED closing)1796 H5FD__mirror_truncate(H5FD_t *_file, hid_t H5_ATTR_UNUSED dxpl_id, hbool_t H5_ATTR_UNUSED closing)
1797 {
1798     unsigned char *xmit_buf  = NULL;
1799     H5FD_mirror_t *file      = (H5FD_mirror_t *)_file;
1800     herr_t         ret_value = SUCCEED;
1801 
1802     FUNC_ENTER_STATIC
1803 
1804     LOG_OP_CALL(FUNC);
1805 
1806     file->xmit.xmit_count = (file->xmit_i)++;
1807     file->xmit.op         = H5FD_MIRROR_OP_TRUNCATE;
1808 
1809     xmit_buf = H5FL_BLK_MALLOC(xmit, H5FD_MIRROR_XMIT_BUFFER_MAX);
1810     if (NULL == xmit_buf)
1811         HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, FAIL, "unable to allocate xmit buffer");
1812 
1813     if (H5FD_mirror_xmit_encode_header(xmit_buf, &(file->xmit)) != H5FD_MIRROR_XMIT_HEADER_SIZE)
1814         HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "unable to encode truncate");
1815 
1816     LOG_XMIT_BYTES("truncate", xmit_buf, H5FD_MIRROR_XMIT_HEADER_SIZE);
1817 
1818     if (HDwrite(file->sock_fd, xmit_buf, H5FD_MIRROR_XMIT_HEADER_SIZE) < 0)
1819         HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "unable to transmit truncate");
1820 
1821     if (H5FD__mirror_verify_reply(file) == FAIL)
1822         HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "invalid reply");
1823 
1824 done:
1825     if (xmit_buf)
1826         xmit_buf = H5FL_BLK_FREE(xmit, xmit_buf);
1827 
1828     FUNC_LEAVE_NOAPI(ret_value)
1829 } /* end H5FD__mirror_truncate() */
1830 
1831 /*-------------------------------------------------------------------------
1832  * Function:    H5FD__mirror_lock
1833  *
1834  * Purpose:     To place an advisory lock on a file.
1835  *              The lock type to apply depends on the parameter "rw":
1836  *                      TRUE--opens for write: an exclusive lock
1837  *                      FALSE--opens for read: a shared lock
1838  *
1839  * Return:      SUCCEED/FAIL
1840  *-------------------------------------------------------------------------
1841  */
1842 static herr_t
H5FD__mirror_lock(H5FD_t * _file,hbool_t rw)1843 H5FD__mirror_lock(H5FD_t *_file, hbool_t rw)
1844 {
1845     H5FD_mirror_xmit_lock_t xmit_lock;
1846     unsigned char *         xmit_buf  = NULL;
1847     H5FD_mirror_t *         file      = (H5FD_mirror_t *)_file;
1848     herr_t                  ret_value = SUCCEED;
1849 
1850     FUNC_ENTER_STATIC
1851 
1852     LOG_OP_CALL(FUNC);
1853 
1854     file->xmit.xmit_count = (file->xmit_i)++;
1855     file->xmit.op         = H5FD_MIRROR_OP_LOCK;
1856 
1857     xmit_lock.pub = file->xmit;
1858     xmit_lock.rw  = (uint64_t)rw;
1859 
1860     xmit_buf = H5FL_BLK_MALLOC(xmit, H5FD_MIRROR_XMIT_BUFFER_MAX);
1861     if (NULL == xmit_buf)
1862         HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, FAIL, "unable to allocate xmit buffer");
1863 
1864     if (H5FD_mirror_xmit_encode_lock(xmit_buf, &xmit_lock) != H5FD_MIRROR_XMIT_LOCK_SIZE)
1865         HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "unable to encode lock");
1866 
1867     LOG_XMIT_BYTES("lock", xmit_buf, H5FD_MIRROR_XMIT_LOCK_SIZE);
1868 
1869     if (HDwrite(file->sock_fd, xmit_buf, H5FD_MIRROR_XMIT_LOCK_SIZE) < 0)
1870         HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "unable to transmit lock");
1871 
1872     if (H5FD__mirror_verify_reply(file) == FAIL)
1873         HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "invalid reply");
1874 
1875 done:
1876     if (xmit_buf)
1877         xmit_buf = H5FL_BLK_FREE(xmit, xmit_buf);
1878 
1879     FUNC_LEAVE_NOAPI(ret_value);
1880 } /* end H5FD__mirror_lock */
1881 
1882 /*-------------------------------------------------------------------------
1883  * Function:    H5FD__mirror_unlock
1884  *
1885  * Purpose:     Remove the existing lock on the file.
1886  *
1887  * Return:      SUCCEED/FAIL
1888  *-------------------------------------------------------------------------
1889  */
1890 static herr_t
H5FD__mirror_unlock(H5FD_t * _file)1891 H5FD__mirror_unlock(H5FD_t *_file)
1892 {
1893     unsigned char *xmit_buf  = NULL;
1894     H5FD_mirror_t *file      = (H5FD_mirror_t *)_file;
1895     herr_t         ret_value = SUCCEED;
1896 
1897     FUNC_ENTER_STATIC
1898 
1899     LOG_OP_CALL(FUNC);
1900 
1901     file->xmit.xmit_count = (file->xmit_i)++;
1902     file->xmit.op         = H5FD_MIRROR_OP_UNLOCK;
1903 
1904     xmit_buf = H5FL_BLK_MALLOC(xmit, H5FD_MIRROR_XMIT_BUFFER_MAX);
1905     if (NULL == xmit_buf)
1906         HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, FAIL, "unable to allocate xmit buffer");
1907 
1908     if (H5FD_mirror_xmit_encode_header(xmit_buf, &(file->xmit)) != H5FD_MIRROR_XMIT_HEADER_SIZE)
1909         HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "unable to encode unlock");
1910 
1911     LOG_XMIT_BYTES("unlock", xmit_buf, H5FD_MIRROR_XMIT_HEADER_SIZE);
1912 
1913     if (HDwrite(file->sock_fd, xmit_buf, H5FD_MIRROR_XMIT_HEADER_SIZE) < 0)
1914         HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "unable to transmit unlock");
1915 
1916     if (H5FD__mirror_verify_reply(file) == FAIL)
1917         HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "invalid reply");
1918 
1919 done:
1920     if (xmit_buf)
1921         xmit_buf = H5FL_BLK_FREE(xmit, xmit_buf);
1922 
1923     FUNC_LEAVE_NOAPI(ret_value);
1924 } /* end H5FD__mirror_unlock */
1925 
1926 #endif /* H5_HAVE_MIRROR_VFD */
1927