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