* Snapshot version 1.12 release 1-3. Update version to 1.12.1-4. * First cut of the H5 public API documentation. (#80) * First cut of the H5 public API documentation. * Added H5Z "bonus track." * Applied Quincey's patch. * Added the missing patches from Quincey's original patch. * H5PL (complete) and basic H5VL API documentation. * Added H5I API docs. * Added H5L API docs. * First installment from Elena's H5T batch. * Second installment of Elena's H5T batch. * Final installment of Elena's H5T batch. * Full set of current H5F documentation. (#105) * First cut of the H5 public API documentation. * Added H5Z "bonus track." * Applied Quincey's patch. * Added the missing patches from Quincey's original patch. * H5PL (complete) and basic H5VL API documentation. * Added H5I API docs. * Added H5L API docs. * First installment from Elena's H5T batch. * Second installment of Elena's H5T batch. * Final installment of Elena's H5T batch. * Migrated documentation for SWMR functions. * Catching up on MDC functions. * Integrated the H5F MDC function documentation. * Added MDC and parallel H5F functions. * Slightly updated main page. * Added doxygen/dox/H5AC_cache_config_t.dox to MANIFEST. * Doxygen - added (mostly) beginner functions (#112) * Doxygen - added (mostly) beginner functions * Removed duplicate H5Pset_szip function * Add src/H5module.h to MANIFEST. * close #195. (#196) * Update HDF5PluginMacros.cmake * Update HDF5PluginMacros.cmake * Avoid aligned access for references by decoding into temporary buffer and then copying the result into the actual buffer. Update test to be more thorough with using compound datatype fields everywhere. (#206) * Modify temporary rpath for testing in java example scripts. (#230) * Fix undefined left shifting of negative numbers (#338) Undefined Bahavior Sanitizer errored here about left shifting negative numbers. * Fixes various warnings noticed on Windows (#425) * Fixes various warnings noticed on Windows - Adds a prototype for our implementation of vasprintf - Return type of H5_get_utf16_str() is now non-const - Fixes possible uninitialized return type in Wremove_utf8 - Better isolation of fork() code in accum.c:test_swmr_write_big() - Better isolation of non-zlib code in dsets.c:test_filter_delete() - Removed unused variable in trefer.c:test_reference_cmpnd_obj() * Fixes clang-format issues * Applied clang-tidy readability-non-const-parameter warning fixes auto… (#429) * Automatically applied clang-tidy readability-avoid-const-params-in-decls fixes Removes useless const declarations. * Fixed most readability-non-const-parameter warnings These changes were made automatically by clang-tidy, but I manually reverted the changes related to the H5Z_func_t signature. * Reformat source with clang v10.0.1. Co-authored-by: Larry Knox <lrknox@hdfgroup.org> * Added C++11 override keyword where appropriate (#433) Added H5_OVERRIDE macro for compatibility with both C++11 and older. * Various clang tidy warning fixes (#448) * Fixed clang-tidy bugprone-reserved-identifier warnings * Fixed clang-tidy bugprone-assert-side-effect warnings * Fixed clang-tidy bugprone-copy-constructor-init warning * Fixed clang-tidy readability-redundant-preprocessor warning For error_test.c the removed code was already dead, because it was in the else of an `#if H5_USE_16_API` block. Based on H5Location.h, I think p_get_ref_obj_type was meant to be in `#ifndef DOXYGEN_SHOULD_SKIP_THIS` and an `#endif` was missing. Similarly, in the header, getObjTypeByIdx is only in H5_NO_DEPRECATED_SYMBOLS, not DOXYGEN_SHOULD_SKIP_THIS. * Fixed clang-tidy readability-redundant-string-init warnings * Fixed some clang-tidy performance-type-promotion-in-math-fn warnings * Fixed clang-tidy performance-unnecessary-value-param warnings * Reformat source with clang v10.0.1. Co-authored-by: Larry Knox <lrknox@hdfgroup.org> * Removed checks/workarounds for pre-C++89 compatibility (#449) After 30+ years, just assume that the following exist: - extension-less includes - namespaces - std:: - static_cast - bool * Fixed all clang-tidy bugprone-suspicious-string-compare warnings (#451) * Fixed all clang-tidy bugprone-suspicious-string-compare warnings This change was generated entirely by clang-tidy itself. * Reformat code with clang v10.0.1. Co-authored-by: Larry Knox <lrknox@hdfgroup.org> * Remove 2 functions incorrectly merged from develop in a cherry-pick merge of PR #451. * Simplified hl parsing (#399) * Stop using global variables to share parse context with the lexer. The lexer uses an unconventional strategy for parsing lexical categories NUMBER (decimal numbers) and STRING (double-quoted strings) that involves sharing the parse context with the lexer using global variables. There are a couple of problems with that. First, the lexer is too complicated for the simple tokenization it performs—it's hard to tell if it is correct. Second, as @seanm points out, the shared global variables spill into the namespace shared by other libraries and application programs—e.g., VTK. * Regenerate source files from *.[yl]. * Replace strndup, which isn't available on Windows, with a custom routine, `trim_quotes`, that produces a copy of its `const char *` argument with leading and trailing double quotes ('"') removed. While I am here, remove the unnecessary statement `BEGIN INITIAL;`, which I should have deleted in a previous commit. * Regenerate .c from .l. * You haven't programmed in C until you have programmed in High-Definition (HD) C. * \#include "H5private.h" for HD* definitions. * Regenerate *.[ch] from *.[yl]. * Removed workarounds for pre-standard inline keyword (#423) Fixes -Wreserved-identifier warnings due to multiple underscores in H5_HAVE___INLINE. * Replaces checks for fork, etc. with checks for unistd.h (#457) * Replaces checks for fork, etc. with H5_HAVE_UNISTD_H Code previously checked for individual POSIX API calls using H5_HAVE_FORK, etc. The calls we use have been standardized for decades and available via unistd.h. Some test messages that were missing when tests are skipped due to a lack of unistd.h were also added. The configure checks for individual POSIX API calls will be removed in a later commit. * Stupid formatter * develop JNI export references and java updates (#467) * OESS-98 convert plugin option to FetchContent, add tests * Fixes for pkcfg files because of plugin option * OESS-98 fix tools test for plugins * Keep doxygen comments under 100 chars long - format hint * Whitespace * HDFFV-11144 - Reclassify CMake messages * HDFFV-11099/11100 added help text * Reworked switch statement to compare string instead * Fix typo * Update CDash mode * Correct name of threadsafe * Correct option name * Undo accidental commit * Note LLVM 10 to 11 format default changes * Update format plugin * Undo clang-format version 11 changes * One more correction * Update supported platforms * Revert whitespace changes * Correct whitespace * Changes from PR#3 * HDFFV-11213 added option to control gcc10 warnings diagnostics * HDFFV-11212 Use the new references correctly in JNI utility and tests * format source * Fix typo * Add new test file * HDFFV-11212 - update test and remove unused arg * Minor non-space formatting changes * Use H5I_INVALID_ID instead of "-1" * source formatting * add missing testfile, update jni function * Undo commit of debug code * remove mislocated file * Fix h5repack test for handling of fapls and id close * Update h5diff test files usage text * HDFFV-11212 add new ref tests for JNI export dataset * src format update * Remove blank line typo * src format typo * long double requires %Lg * Another long double foramt specifer S.B. %Lg * issue with t128bit test * Windows issue with h5dump and type. * Fix review issues * refactor function nesting and fix error checks * format fixes * Remove untested functions and javadoc quiet comments * Restore TRY block. * Change string append errors to memory exception * revert to H5_JNI_FATAL_ERROR - support functions need work * Add assertion error for h5util functions * remove duplicate function * format fix * Revert HD function error handling * Update copyright comments * GH #386 java folder copyright corrections * Whitespace * GH #359 implement and fix tools 1.6 API usage * remove excessive comments * Flip inits to correct ifdef section * rework ifdef to be simpler * format issue * Reformat ifdef inits * remove static attribute * format compliance * Update names * Revert because logic relies on float not being int * Changes noticed from creating merge of #412 * Double underscore change * Correct compiler version variable used * Remove header guard underscores * Whitespace cleanup * Split format source and commit changes on repo push * remove pre-split setting * Change windows TS to use older VS. * correct window os name * HDFFV-11212 JNI export util and Javadoc * Suggested review changes * Another change found * Committing clang-format changes Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com> * Fix display of long double in tools (#469) * OESS-98 convert plugin option to FetchContent, add tests * Fixes for pkcfg files because of plugin option * OESS-98 fix tools test for plugins * Keep doxygen comments under 100 chars long - format hint * Whitespace * HDFFV-11144 - Reclassify CMake messages * HDFFV-11099/11100 added help text * Reworked switch statement to compare string instead * Fix typo * Update CDash mode * Correct name of threadsafe * Correct option name * Undo accidental commit * Note LLVM 10 to 11 format default changes * Update format plugin * Undo clang-format version 11 changes * One more correction * Update supported platforms * Revert whitespace changes * Correct whitespace * Changes from PR#3 * HDFFV-11213 added option to control gcc10 warnings diagnostics * HDFFV-11212 Use the new references correctly in JNI utility and tests * format source * Fix typo * Add new test file * HDFFV-11212 - update test and remove unused arg * Minor non-space formatting changes * Use H5I_INVALID_ID instead of "-1" * source formatting * add missing testfile, update jni function * Undo commit of debug code * remove mislocated file * Fix h5repack test for handling of fapls and id close * Update h5diff test files usage text * HDFFV-11212 add new ref tests for JNI export dataset * src format update * Remove blank line typo * src format typo * long double requires %Lg * Another long double foramt specifer S.B. %Lg * issue with t128bit test * Windows issue with h5dump and type. * Fix review issues * refactor function nesting and fix error checks * format fixes * Remove untested functions and javadoc quiet comments * Restore TRY block. * Change string append errors to memory exception * revert to H5_JNI_FATAL_ERROR - support functions need work * Add assertion error for h5util functions * remove duplicate function * format fix * Revert HD function error handling * Update copyright comments * GH #386 java folder copyright corrections * Whitespace * GH #359 implement and fix tools 1.6 API usage * remove excessive comments * Flip inits to correct ifdef section * rework ifdef to be simpler * format issue * Reformat ifdef inits * remove static attribute * format compliance * Update names * Revert because logic relies on float not being int * Changes noticed from creating merge of #412 * Double underscore change * Correct compiler version variable used * Remove header guard underscores * Whitespace cleanup * Split format source and commit changes on repo push * remove pre-split setting * Change windows TS to use older VS. * correct window os name * HDFFV-11212 JNI export util and Javadoc * Suggested review changes * Another change found * Committing clang-format changes * HDFFV-11113 long double in tools * HDFFV-11113 add note Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com> * Update clang config (#473) * Update clang config to put H5E_BEGIN_TRY / H5E_END_TRY on separate lines, empty C++ methods on separate lines, understand that ALL_MEMBERS / UNIQUE_MEMBERS are foreach macros, and properly skip the 'config' directory in the find command without emiting a warning * Committing clang-format changes Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com> * Correct syntax error. (#474) a Fortran compile -> a Fortran compiler * Cleans up a couple of MSVC warnings in testhdf5 (#475) * Fixes a few testhdf5 warnings raised in Visual Studio Visual Studio is grumpier about treating pointers like integers than gcc. * Committing clang-format changes Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com> * Fix typos and grammar errors. (#476) * Suppresses the tcheck_version test's abort dialog on Windows (#477) * Suppresses the tcheck_version test's abort dialog on Windows Windows raises a modal abort/retry/ignore dialog box when CRT calls abort(). This change installs a report hook that suppresses the dialog so that the CMake tests don't time out waiting for a nonexistent user to click a dialog box. * Committing clang-format changes * Removes __cdecl from callback Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com> * Rerun genparser. * Fix merge issues and rerun genparser. Co-authored-by: Gerd Heber <gheber@hdfgroup.org> Co-authored-by: bljhdf <58825073+bljhdf@users.noreply.github.com> Co-authored-by: H. Joe Lee <hyoklee@hdfgroup.org> Co-authored-by: Quincey Koziol <quincey@koziol.cc> Co-authored-by: Sean McBride <sean@rogue-research.com> Co-authored-by: Dana Robinson <43805+derobins@users.noreply.github.com> Co-authored-by: David Young <dyoung@hdfgroup.org> Co-authored-by: Allen Byrne <50328838+byrnHDF@users.noreply.github.com> Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Quincey Koziol <koziol@lbl.gov>
1051 lines
35 KiB
C
1051 lines
35 KiB
C
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
* Copyright by The HDF Group. *
|
|
* All rights reserved. *
|
|
* *
|
|
* This file is part of HDF5. The full HDF5 copyright notice, including *
|
|
* terms governing use, modification, and redistribution, is contained in *
|
|
* the COPYING file, which can be found at the root of the source code *
|
|
* distribution tree, or in https://www.hdfgroup.org/licenses. *
|
|
* If you do not have access to either file, you may request a copy from *
|
|
* help@hdfgroup.org. *
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
|
|
/*
|
|
* Remote writer process for the mirror (socket) VFD.
|
|
*
|
|
* Writer is started with arguments for slaved port.
|
|
* Awaits a connection on the socket.
|
|
* Handles instructions from the master 'Driver' process.
|
|
*
|
|
* Current implementation uses Sec2 as the underlying driver when opening a
|
|
* file. This is reflected in the source (H5FDmirror.c) of the Mirror driver.
|
|
*/
|
|
|
|
#include "mirror_remote.h"
|
|
|
|
#ifdef H5_HAVE_MIRROR_VFD
|
|
|
|
#define HEXDUMP_XMITS 1 /* Toggle whether to print xmit bytes-blob */
|
|
/* in detailed logging */
|
|
#define HEXDUMP_WRITEDATA 0 /* Toggle whether to print bytes to write */
|
|
/* in detailed logging */
|
|
#define LISTENQ 80 /* max pending Driver requests */
|
|
|
|
#define MW_SESSION_MAGIC 0x88F36B32u
|
|
#define MW_SOCK_COMM_MAGIC 0xDF10A157u
|
|
#define MW_OPTS_MAGIC 0x3BA8B462u
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
* Structure: struct mirror_session
|
|
*
|
|
* Bundle of information used to manage the operation of this remote Writer
|
|
* in a "session" with the Driver process.
|
|
*
|
|
* magic (uint32_t)
|
|
* Semi-unique "magic" number used to sanity-check a structure for
|
|
* validity. MUST equal MW_SESSION_MAGIC to be valid.
|
|
*
|
|
* sockfd (int)
|
|
* File descriptor to the socket.
|
|
* Used for receiving bytes from and writing bytes to the Driver
|
|
* across the network.
|
|
* If not NULL, should be a valid descriptor.
|
|
*
|
|
* token (uint32t)
|
|
* Number used to help sanity-check received transmission from the Writer.
|
|
* Each Driver/Writer pairing should have a semi-unique "token" to help
|
|
* guard against commands from the wrong entity.
|
|
*
|
|
* xmit_count (uint32_t)
|
|
* Record of trasmissions received from the Driver. While the transmission
|
|
* protocol should be trustworthy, this serves as an additional guard.
|
|
* Starts a 0 and should be incremented for each one-way transmission.
|
|
*
|
|
* file (H5FD_t *)
|
|
* Virtual File handle for the hdf5 file.
|
|
* Set on file open if H5Fopen() is successful. If NULL, it is invalid.
|
|
*
|
|
* log_verbosity (unsigned int)
|
|
* The verbosity level for logging. Should be set to one of the values
|
|
* defined at the top of this file.
|
|
*
|
|
* log_stream (FILE *)
|
|
* File pointer to which logging output is written. Starts (and ends)
|
|
* with a default stream, such as stdout, but can be overridden at
|
|
* runtime.
|
|
*
|
|
* reply (H5FD_mirror_xmit_reply_t)
|
|
* Structure space for persistent reply data.
|
|
* Should be initialized with basic header info (magic, version, op),
|
|
* then with session info (token, xmit count), and finally with specific
|
|
* reply info (update xmit_count, status code, and message) before
|
|
* transmission.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
struct mirror_session {
|
|
uint32_t magic;
|
|
int sockfd;
|
|
uint32_t token;
|
|
uint32_t xmit_count;
|
|
H5FD_t * file;
|
|
loginfo_t * loginfo;
|
|
H5FD_mirror_xmit_reply_t reply;
|
|
};
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
* Structure: struct sock_comm
|
|
*
|
|
* Structure for placing the data read and pre-processed from Driver in an
|
|
* organized fashion. Useful for pre-processing a received xmit.
|
|
*
|
|
* magic (uint32_t)
|
|
* Semi-unique number to sanity-check structure pointer and validity.
|
|
* Must equal MW_SOCK_COMM_MAGIC to be valid.
|
|
*
|
|
* recd_die (int)
|
|
* "Boolean" flag indicating that an explicit shutdown/kill/die command
|
|
* was received. Potentially useful for debugging and or "manual"
|
|
* operation of the program.
|
|
* 0 indicates normal operation, non-0 (1) indicates to die.
|
|
*
|
|
* xmit_recd (H5FD_mirror_xmit_t *)
|
|
* Structure pointer for the "xmit header" as decoded from the raw
|
|
* binary stream read from the socket.
|
|
*
|
|
* raw (char *)
|
|
* Pointer to a raw byte array, for storing data as read from the
|
|
* socket. Bytes buffer is decoded into xmit_t header and derivative
|
|
* structures.
|
|
*
|
|
* raw_size (size_t)
|
|
* Give the size of the `raw` buffer.
|
|
*
|
|
* ---------------------------------------------------------------------------
|
|
*/
|
|
struct sock_comm {
|
|
uint32_t magic;
|
|
int recd_die;
|
|
H5FD_mirror_xmit_t *xmit_recd;
|
|
char * raw;
|
|
size_t raw_size;
|
|
};
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
* Structure: struct mirror_writer_opts
|
|
*
|
|
* Container for default values and options as parsed from the command line.
|
|
* Currently rather vestigal, but may be expanded and/or moved to be set by
|
|
* Server and passed around as an argument.
|
|
*
|
|
* magic (uint32_t)
|
|
* Semi-unique number to sanity-check structure pointer and validity.
|
|
* Must equal MW_OPTS_MAGIC to be valid.
|
|
*
|
|
* logpath (char *)
|
|
* String pointer. Allocated at runtime.
|
|
* Specifies file location for logging output.
|
|
* May be NULL -- uses default output (e.g., stdout).
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
struct mirror_writer_opts {
|
|
uint32_t magic;
|
|
char * logpath;
|
|
};
|
|
|
|
static void mybzero(void *dest, size_t size);
|
|
|
|
static int do_open(struct mirror_session *session, const H5FD_mirror_xmit_open_t *xmit_open);
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
* Function: mybzero
|
|
*
|
|
* Purpose: Introduce bzero without neededing it on the system.
|
|
*
|
|
* Programmer: Jacob Smith
|
|
* 2020-03-30
|
|
* ---------------------------------------------------------------------------
|
|
*/
|
|
static void
|
|
mybzero(void *dest, size_t size)
|
|
{
|
|
size_t i = 0;
|
|
char * s = NULL;
|
|
HDassert(dest);
|
|
s = (char *)dest;
|
|
for (i = 0; i < size; i++) {
|
|
*(s + i) = 0;
|
|
}
|
|
} /* end mybzero() */
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
* Function: session_init
|
|
*
|
|
* Purpose: Populate mirror_session structure with default and
|
|
* options-drived values.
|
|
*
|
|
* Return: An allocated mirror_session structure pointer on success,
|
|
* else NULL.
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
static struct mirror_session *
|
|
session_init(struct mirror_writer_opts *opts)
|
|
{
|
|
struct mirror_session *session = NULL;
|
|
|
|
mirror_log(NULL, V_INFO, "session_init()");
|
|
|
|
if (NULL == opts || opts->magic != MW_OPTS_MAGIC) {
|
|
mirror_log(NULL, V_ERR, "invalid opts pointer");
|
|
goto error;
|
|
}
|
|
|
|
session = (struct mirror_session *)HDmalloc(sizeof(struct mirror_session));
|
|
if (session == NULL) {
|
|
mirror_log(NULL, V_ERR, "can't allocate session structure");
|
|
goto error;
|
|
}
|
|
|
|
session->magic = MW_SESSION_MAGIC;
|
|
session->sockfd = -1;
|
|
session->xmit_count = 0;
|
|
session->token = 0;
|
|
session->file = NULL;
|
|
|
|
session->reply.pub.magic = H5FD_MIRROR_XMIT_MAGIC;
|
|
session->reply.pub.version = H5FD_MIRROR_XMIT_CURR_VERSION;
|
|
session->reply.pub.op = H5FD_MIRROR_OP_REPLY;
|
|
session->reply.pub.session_token = 0;
|
|
mybzero(session->reply.message, H5FD_MIRROR_STATUS_MESSAGE_MAX);
|
|
|
|
/* Options-derived population
|
|
*/
|
|
|
|
session->loginfo = mirror_log_init(opts->logpath, "W- ", MIRROR_LOG_DEFAULT_VERBOSITY);
|
|
|
|
return session;
|
|
|
|
error:
|
|
if (session) {
|
|
HDfree(session);
|
|
}
|
|
return NULL;
|
|
} /* end session_init() */
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
* Function: session_stop
|
|
*
|
|
* Purpose: Stop and clean up a session.
|
|
* Only do this as part of program termination or aborting startup.
|
|
*
|
|
* Return: 0 on success, or negative sum of errors encountered.
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
static int
|
|
session_stop(struct mirror_session *session)
|
|
{
|
|
int ret_value = 0;
|
|
|
|
HDassert(session && (session->magic == MW_SESSION_MAGIC));
|
|
|
|
mirror_log(session->loginfo, V_INFO, "session_stop()");
|
|
|
|
/* Close HDF5 file if it is still open (probably in error) */
|
|
if (session->file) {
|
|
mirror_log(session->loginfo, V_WARN, "HDF5 file still open at cleanup");
|
|
if (H5FDclose(session->file) < 0) {
|
|
mirror_log(session->loginfo, V_ERR, "H5FDclose() during cleanup!");
|
|
ret_value--;
|
|
}
|
|
}
|
|
|
|
/* Socket will be closed by parent side of server fork after exit */
|
|
|
|
/* Close custom logging stream */
|
|
if (mirror_log_term(session->loginfo) < 0) {
|
|
mirror_log(NULL, V_ERR, "Problem closing logging stream");
|
|
ret_value--;
|
|
}
|
|
session->loginfo = NULL;
|
|
|
|
/* Invalidate and release structure */
|
|
session->magic++;
|
|
HDfree(session);
|
|
|
|
return ret_value;
|
|
} /* end session_stop() */
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
* Function: session_start
|
|
*
|
|
* Purpose: Initiate session, open files.
|
|
*
|
|
* Return: Success: A valid mirror_session pointer which must later be
|
|
* cleaned up with session_stop().
|
|
* Failure: NULL, after cleaning up after itself.
|
|
* ---------------------------------------------------------------------------
|
|
*/
|
|
static struct mirror_session *
|
|
session_start(int socketfd, const H5FD_mirror_xmit_open_t *xmit_open)
|
|
{
|
|
struct mirror_session * session = NULL;
|
|
struct mirror_writer_opts opts;
|
|
#if 0 /* TODO: behaviro option */
|
|
char logpath[H5FD_MIRROR_XMIT_FILEPATH_MAX] = "";
|
|
#endif
|
|
|
|
mirror_log(NULL, V_INFO, "session_start()");
|
|
|
|
if (FALSE == H5FD_mirror_xmit_is_open(xmit_open)) {
|
|
mirror_log(NULL, V_ERR, "invalid OPEN xmit");
|
|
return NULL;
|
|
}
|
|
|
|
opts.magic = MW_OPTS_MAGIC;
|
|
#if 0 /* TODO: behavior option */
|
|
HDsnprintf(logpath, H5FD_MIRROR_XMIT_FILEPATH_MAX, "%s.log",
|
|
xmit_open->filename);
|
|
opts.logpath = logpath;
|
|
#else
|
|
opts.logpath = NULL;
|
|
#endif
|
|
|
|
session = session_init(&opts);
|
|
if (NULL == session) {
|
|
mirror_log(NULL, V_ERR, "can't instantiate session");
|
|
goto error;
|
|
}
|
|
|
|
session->sockfd = socketfd;
|
|
|
|
if (do_open(session, xmit_open) < 0) {
|
|
mirror_log(NULL, V_ERR, "unable to open file");
|
|
goto error;
|
|
}
|
|
|
|
return session;
|
|
|
|
error:
|
|
if (session != NULL) {
|
|
if (session_stop(session) < 0) {
|
|
mirror_log(NULL, V_WARN, "Can't abort session init");
|
|
}
|
|
session = NULL;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
* Function: _xmit_reply
|
|
*
|
|
* Purpose: Common operations to send a reply xmit through the session.
|
|
*
|
|
* Return: 0 on success, -1 if error.
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
static int
|
|
_xmit_reply(struct mirror_session *session)
|
|
{
|
|
unsigned char xmit_buf[H5FD_MIRROR_XMIT_REPLY_SIZE];
|
|
H5FD_mirror_xmit_reply_t *reply = &(session->reply);
|
|
|
|
HDassert(session && (session->magic == MW_SESSION_MAGIC));
|
|
|
|
mirror_log(session->loginfo, V_ALL, "_xmit_reply()");
|
|
|
|
reply->pub.xmit_count = session->xmit_count++;
|
|
if (H5FD_mirror_xmit_encode_reply(xmit_buf, (const H5FD_mirror_xmit_reply_t *)reply) !=
|
|
H5FD_MIRROR_XMIT_REPLY_SIZE) {
|
|
mirror_log(session->loginfo, V_ERR, "can't encode reply");
|
|
return -1;
|
|
}
|
|
|
|
mirror_log(session->loginfo, V_ALL, "reply xmit data\n```");
|
|
mirror_log_bytes(session->loginfo, V_ALL, H5FD_MIRROR_XMIT_REPLY_SIZE, (const unsigned char *)xmit_buf);
|
|
mirror_log(session->loginfo, V_ALL, "```");
|
|
|
|
if (HDwrite(session->sockfd, xmit_buf, H5FD_MIRROR_XMIT_REPLY_SIZE) < 0) {
|
|
mirror_log(session->loginfo, V_ERR, "can't write reply to Driver");
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
} /* end _xmit_reply() */
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
* Function: reply_ok
|
|
*
|
|
* Purpose: Send an OK reply through the session.
|
|
*
|
|
* Return: 0 on success, -1 if error.
|
|
* ---------------------------------------------------------------------------
|
|
*/
|
|
static int
|
|
reply_ok(struct mirror_session *session)
|
|
{
|
|
H5FD_mirror_xmit_reply_t *reply = &(session->reply);
|
|
|
|
HDassert(session && (session->magic == MW_SESSION_MAGIC));
|
|
|
|
mirror_log(session->loginfo, V_ALL, "reply_ok()");
|
|
|
|
reply->status = H5FD_MIRROR_STATUS_OK;
|
|
mybzero(reply->message, H5FD_MIRROR_STATUS_MESSAGE_MAX);
|
|
return _xmit_reply(session);
|
|
} /* end reply_ok() */
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
* Function: reply_error
|
|
*
|
|
* Purpose: Send an ERROR reply with message through the session.
|
|
* Message may be cut short if it would overflow the available
|
|
* buffer in the xmit.
|
|
*
|
|
* Return: 0 on success, -1 if error.
|
|
* ---------------------------------------------------------------------------
|
|
*/
|
|
static int
|
|
reply_error(struct mirror_session *session, const char *msg)
|
|
{
|
|
H5FD_mirror_xmit_reply_t *reply = &(session->reply);
|
|
|
|
HDassert(session && (session->magic == MW_SESSION_MAGIC));
|
|
|
|
mirror_log(session->loginfo, V_ALL, "reply_error(%s)", msg);
|
|
|
|
reply->status = H5FD_MIRROR_STATUS_ERROR;
|
|
HDsnprintf(reply->message, H5FD_MIRROR_STATUS_MESSAGE_MAX - 1, "%s", msg);
|
|
return _xmit_reply(session);
|
|
} /* end reply_error() */
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
* Function: do_close
|
|
*
|
|
* Purpose: Handle an CLOSE operation.
|
|
*
|
|
* Return: 0 on success, -1 if error.
|
|
* ---------------------------------------------------------------------------
|
|
*/
|
|
static int
|
|
do_close(struct mirror_session *session)
|
|
{
|
|
|
|
HDassert(session && (session->magic == MW_SESSION_MAGIC));
|
|
|
|
mirror_log(session->loginfo, V_INFO, "do_close()");
|
|
|
|
if (NULL == session->file) {
|
|
mirror_log(session->loginfo, V_ERR, "no file to close!");
|
|
reply_error(session, "no file to close");
|
|
return -1;
|
|
}
|
|
|
|
if (H5FDclose(session->file) < 0) {
|
|
mirror_log(session->loginfo, V_ERR, "H5FDclose()");
|
|
reply_error(session, "H5FDclose()");
|
|
return -1;
|
|
}
|
|
session->file = NULL;
|
|
|
|
if (reply_ok(session) < 0) {
|
|
mirror_log(session->loginfo, V_ERR, "can't reply");
|
|
reply_error(session, "ok reply failed; session contaminated");
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
} /* end do_close() */
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
* Function: do_lock
|
|
*
|
|
* Purpose: Handle a LOCK operation.
|
|
*
|
|
* Return: 0 on success, -1 if error.
|
|
* ---------------------------------------------------------------------------
|
|
*/
|
|
static int
|
|
do_lock(struct mirror_session *session, const unsigned char *xmit_buf)
|
|
{
|
|
size_t decode_ret = 0;
|
|
H5FD_mirror_xmit_lock_t xmit_lock;
|
|
|
|
HDassert(session && (session->magic == MW_SESSION_MAGIC) && xmit_buf);
|
|
|
|
mirror_log(session->loginfo, V_INFO, "do_lock()");
|
|
|
|
decode_ret = H5FD_mirror_xmit_decode_lock(&xmit_lock, xmit_buf);
|
|
if (H5FD_MIRROR_XMIT_LOCK_SIZE != decode_ret) {
|
|
mirror_log(session->loginfo, V_ERR, "can't decode set-eoa xmit");
|
|
reply_error(session, "remote xmit_eoa_t decoding size failure");
|
|
return -1;
|
|
}
|
|
|
|
if (!H5FD_mirror_xmit_is_lock(&xmit_lock)) {
|
|
mirror_log(session->loginfo, V_ERR, "not a set-eoa xmit");
|
|
reply_error(session, "remote xmit_eoa_t decode failure");
|
|
return -1;
|
|
}
|
|
mirror_log(session->loginfo, V_INFO, "lock rw: (%d)", xmit_lock.rw);
|
|
|
|
if (H5FDlock(session->file, (hbool_t)xmit_lock.rw) < 0) {
|
|
mirror_log(session->loginfo, V_ERR, "H5FDlock()");
|
|
reply_error(session, "remote H5FDlock() failure");
|
|
return -1;
|
|
}
|
|
|
|
if (reply_ok(session) < 0) {
|
|
mirror_log(session->loginfo, V_ERR, "can't reply");
|
|
reply_error(session, "ok reply failed; session contaminated");
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
} /* end do_lock() */
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
* Function: do_open
|
|
*
|
|
* Purpose: Handle an OPEN operation.
|
|
*
|
|
* Return: 0 on success, -1 if error.
|
|
* ---------------------------------------------------------------------------
|
|
*/
|
|
static int
|
|
do_open(struct mirror_session *session, const H5FD_mirror_xmit_open_t *xmit_open)
|
|
{
|
|
hid_t fapl_id = H5I_INVALID_HID;
|
|
unsigned _flags = 0;
|
|
haddr_t _maxaddr = HADDR_UNDEF;
|
|
|
|
HDassert(session && (session->magic == MW_SESSION_MAGIC) && xmit_open &&
|
|
TRUE == H5FD_mirror_xmit_is_open(xmit_open));
|
|
|
|
mirror_log(session->loginfo, V_INFO, "do_open()");
|
|
|
|
if (0 != xmit_open->pub.xmit_count) {
|
|
mirror_log(session->loginfo, V_ERR, "open with xmit count not zero!");
|
|
reply_error(session, "initial transmission count not zero");
|
|
goto error;
|
|
}
|
|
if (0 != session->token) {
|
|
mirror_log(session->loginfo, V_ERR, "open with token already set!");
|
|
reply_error(session, "initial session token not zero");
|
|
goto error;
|
|
}
|
|
|
|
session->xmit_count = 1;
|
|
session->token = xmit_open->pub.session_token;
|
|
session->reply.pub.session_token = session->token;
|
|
|
|
_flags = (unsigned)xmit_open->flags;
|
|
_maxaddr = (haddr_t)xmit_open->maxaddr;
|
|
|
|
/* Check whether the native size_t on the remote machine (Driver) is larger
|
|
* than that on the local machine; if so, issue a warning.
|
|
* The blob is always an 8-byte bitfield -- check its contents.
|
|
*/
|
|
if (xmit_open->size_t_blob > (uint64_t)((size_t)(-1))) {
|
|
mirror_log(session->loginfo, V_WARN, "Driver size_t is larger than our own");
|
|
}
|
|
|
|
mirror_log(session->loginfo, V_INFO, "to open file %s (flags %d) (maxaddr %d)", xmit_open->filename,
|
|
_flags, _maxaddr);
|
|
|
|
/* Explicitly use Sec2 as the underlying driver for now.
|
|
*/
|
|
fapl_id = H5Pcreate(H5P_FILE_ACCESS);
|
|
if (fapl_id < 0) {
|
|
mirror_log(session->loginfo, V_ERR, "can't create FAPL");
|
|
reply_error(session, "H5Pcreate() failure");
|
|
goto error;
|
|
}
|
|
if (H5Pset_fapl_sec2(fapl_id) < 0) {
|
|
mirror_log(session->loginfo, V_ERR, "can't set FAPL as Sec2");
|
|
reply_error(session, "H5Pset_fapl_sec2() failure");
|
|
goto error;
|
|
}
|
|
|
|
session->file = H5FDopen(xmit_open->filename, _flags, fapl_id, _maxaddr);
|
|
if (NULL == session->file) {
|
|
mirror_log(session->loginfo, V_ERR, "H5FDopen()");
|
|
reply_error(session, "remote H5FDopen() failure");
|
|
goto error;
|
|
}
|
|
|
|
/* FAPL is set and in use; clean up */
|
|
if (H5Pclose(fapl_id) < 0) {
|
|
mirror_log(session->loginfo, V_ERR, "can't set FAPL as Sec2");
|
|
reply_error(session, "H5Pset_fapl_sec2() failure");
|
|
goto error;
|
|
}
|
|
|
|
if (reply_ok(session) < 0) {
|
|
mirror_log(session->loginfo, V_ERR, "can't reply");
|
|
reply_error(session, "ok reply failed; session contaminated");
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
|
|
error:
|
|
if (fapl_id > 0) {
|
|
H5E_BEGIN_TRY
|
|
{
|
|
(void)H5Pclose(fapl_id);
|
|
}
|
|
H5E_END_TRY;
|
|
}
|
|
return -1;
|
|
} /* end do_open() */
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
* Function: do_set_eoa
|
|
*
|
|
* Purpose: Handle a SET_EOA operation.
|
|
*
|
|
* Return: 0 on success, -1 if error.
|
|
* ---------------------------------------------------------------------------
|
|
*/
|
|
static int
|
|
do_set_eoa(struct mirror_session *session, const unsigned char *xmit_buf)
|
|
{
|
|
size_t decode_ret = 0;
|
|
H5FD_mirror_xmit_eoa_t xmit_seoa;
|
|
|
|
HDassert(session && (session->magic == MW_SESSION_MAGIC) && xmit_buf);
|
|
|
|
mirror_log(session->loginfo, V_INFO, "do_set_eoa()");
|
|
|
|
decode_ret = H5FD_mirror_xmit_decode_set_eoa(&xmit_seoa, xmit_buf);
|
|
if (H5FD_MIRROR_XMIT_EOA_SIZE != decode_ret) {
|
|
mirror_log(session->loginfo, V_ERR, "can't decode set-eoa xmit");
|
|
reply_error(session, "remote xmit_eoa_t decoding size failure");
|
|
return -1;
|
|
}
|
|
|
|
if (!H5FD_mirror_xmit_is_set_eoa(&xmit_seoa)) {
|
|
mirror_log(session->loginfo, V_ERR, "not a set-eoa xmit");
|
|
reply_error(session, "remote xmit_eoa_t decode failure");
|
|
return -1;
|
|
}
|
|
|
|
mirror_log(session->loginfo, V_INFO, "set EOA addr %d", xmit_seoa.eoa_addr);
|
|
|
|
if (H5FDset_eoa(session->file, (H5FD_mem_t)xmit_seoa.type, (haddr_t)xmit_seoa.eoa_addr) < 0) {
|
|
mirror_log(session->loginfo, V_ERR, "H5FDset_eoa()");
|
|
reply_error(session, "remote H5FDset_eoa() failure");
|
|
return -1;
|
|
}
|
|
|
|
if (reply_ok(session) < 0) {
|
|
mirror_log(session->loginfo, V_ERR, "can't reply");
|
|
reply_error(session, "ok reply failed; session contaminated");
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
} /* end do_set_eoa() */
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
* Function: do_truncate
|
|
*
|
|
* Purpose: Handle a TRUNCATE operation.
|
|
*
|
|
* Return: 0 on success, -1 if error.
|
|
* ---------------------------------------------------------------------------
|
|
*/
|
|
static int
|
|
do_truncate(struct mirror_session *session)
|
|
{
|
|
|
|
HDassert(session && (session->magic == MW_SESSION_MAGIC));
|
|
|
|
mirror_log(session->loginfo, V_INFO, "do_truncate()");
|
|
|
|
/* default DXPL ID (0), 0 for "FALSE" closing -- both probably unused */
|
|
if (H5FDtruncate(session->file, 0, 0) < 0) {
|
|
mirror_log(session->loginfo, V_ERR, "H5FDtruncate()");
|
|
reply_error(session, "remote H5FDtruncate() failure");
|
|
return -1;
|
|
}
|
|
|
|
if (reply_ok(session) < 0) {
|
|
mirror_log(session->loginfo, V_ERR, "can't reply");
|
|
reply_error(session, "ok reply failed; session contaminated");
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
} /* end do_truncate() */
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
* Function: do_unlock
|
|
*
|
|
* Purpose: Handle an UNLOCK operation.
|
|
*
|
|
* Return: 0 on success, -1 if error.
|
|
* ---------------------------------------------------------------------------
|
|
*/
|
|
static int
|
|
do_unlock(struct mirror_session *session)
|
|
{
|
|
HDassert(session && (session->magic == MW_SESSION_MAGIC));
|
|
|
|
mirror_log(session->loginfo, V_INFO, "do_unlock()");
|
|
|
|
if (H5FDunlock(session->file) < 0) {
|
|
mirror_log(session->loginfo, V_ERR, "H5FDunlock()");
|
|
reply_error(session, "remote H5FDunlock() failure");
|
|
return -1;
|
|
}
|
|
|
|
if (reply_ok(session) < 0) {
|
|
mirror_log(session->loginfo, V_ERR, "can't reply");
|
|
reply_error(session, "ok reply failed; session contaminated");
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
} /* end do_unlock() */
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
* Function: do_write
|
|
*
|
|
* Purpose: Handle a WRITE operation.
|
|
* Receives command, replies; receives & writes data, replies.
|
|
*
|
|
* It is known that this results in suboptimal performance,
|
|
* but handling both small and very, very large write buffers
|
|
* with a single "over the wire" exchange
|
|
* poses design challenges not worth tackling as of March 2020.
|
|
*
|
|
* Return: 0 on success, -1 if error.
|
|
* ---------------------------------------------------------------------------
|
|
*/
|
|
static int
|
|
do_write(struct mirror_session *session, const unsigned char *xmit_buf)
|
|
{
|
|
size_t decode_ret = 0;
|
|
haddr_t addr = 0;
|
|
haddr_t sum_bytes_written = 0;
|
|
H5FD_mem_t type = 0;
|
|
char * buf = NULL;
|
|
ssize_t nbytes_in_packet = 0;
|
|
H5FD_mirror_xmit_write_t xmit_write;
|
|
|
|
HDassert(session && (session->magic == MW_SESSION_MAGIC) && xmit_buf);
|
|
|
|
mirror_log(session->loginfo, V_INFO, "do_write()");
|
|
|
|
if (NULL == session->file) {
|
|
mirror_log(session->loginfo, V_ERR, "no open file!");
|
|
reply_error(session, "no file open on remote");
|
|
return -1;
|
|
}
|
|
|
|
decode_ret = H5FD_mirror_xmit_decode_write(&xmit_write, xmit_buf);
|
|
if (H5FD_MIRROR_XMIT_WRITE_SIZE != decode_ret) {
|
|
mirror_log(session->loginfo, V_ERR, "can't decode write xmit");
|
|
reply_error(session, "remote xmit_write_t decoding size failure");
|
|
return -1;
|
|
}
|
|
|
|
if (!H5FD_mirror_xmit_is_write(&xmit_write)) {
|
|
mirror_log(session->loginfo, V_ERR, "not a write xmit");
|
|
reply_error(session, "remote xmit_write_t decode failure");
|
|
return -1;
|
|
}
|
|
|
|
addr = (haddr_t)xmit_write.offset;
|
|
type = (H5FD_mem_t)xmit_write.type;
|
|
|
|
/* Allocate the buffer once -- re-use between loops.
|
|
*/
|
|
buf = (char *)HDmalloc(sizeof(char) * H5FD_MIRROR_DATA_BUFFER_MAX);
|
|
if (NULL == buf) {
|
|
mirror_log(session->loginfo, V_ERR, "can't allocate databuffer");
|
|
reply_error(session, "can't allocate buffer for receiving data");
|
|
return -1;
|
|
}
|
|
|
|
/* got write signal; ready for data */
|
|
if (reply_ok(session) < 0) {
|
|
mirror_log(session->loginfo, V_ERR, "can't reply");
|
|
reply_error(session, "ok reply failed; session contaminated");
|
|
return -1;
|
|
}
|
|
|
|
mirror_log(session->loginfo, V_INFO, "to write %zu bytes at %zu", xmit_write.size, addr);
|
|
|
|
/* The given write may be:
|
|
* 1. larger than the allowed single buffer size
|
|
* 2. larger than the native size_t of this system
|
|
*
|
|
* Handle all cases by looping, ingesting as much of the stream as possible
|
|
* and writing that part to the file.
|
|
*/
|
|
sum_bytes_written = 0;
|
|
do {
|
|
nbytes_in_packet = HDread(session->sockfd, buf, H5FD_MIRROR_DATA_BUFFER_MAX);
|
|
if (-1 == nbytes_in_packet) {
|
|
mirror_log(session->loginfo, V_ERR, "can't read into databuffer");
|
|
reply_error(session, "can't read data buffer");
|
|
return -1;
|
|
}
|
|
|
|
mirror_log(session->loginfo, V_INFO, "received %zd bytes", nbytes_in_packet);
|
|
if (HEXDUMP_WRITEDATA) {
|
|
mirror_log(session->loginfo, V_ALL, "DATA:\n```");
|
|
mirror_log_bytes(session->loginfo, V_ALL, nbytes_in_packet, (const unsigned char *)buf);
|
|
mirror_log(session->loginfo, V_ALL, "```");
|
|
}
|
|
|
|
mirror_log(session->loginfo, V_INFO, "writing %zd bytes at %zu", nbytes_in_packet,
|
|
(addr + sum_bytes_written));
|
|
|
|
if (H5FDwrite(session->file, type, H5P_DEFAULT, (addr + sum_bytes_written), (size_t)nbytes_in_packet,
|
|
buf) < 0) {
|
|
mirror_log(session->loginfo, V_ERR, "H5FDwrite()");
|
|
reply_error(session, "remote H5FDwrite() failure");
|
|
return -1;
|
|
}
|
|
|
|
sum_bytes_written += (haddr_t)nbytes_in_packet;
|
|
|
|
} while (sum_bytes_written < xmit_write.size); /* end while ingesting */
|
|
|
|
HDfree(buf);
|
|
|
|
/* signal that we're done here and a-ok */
|
|
if (reply_ok(session) < 0) {
|
|
mirror_log(session->loginfo, V_ERR, "can't reply");
|
|
reply_error(session, "ok reply failed; session contaminated");
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
} /* end do_write() */
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
* Function: receive_communique
|
|
*
|
|
* Purpose: Accept bytes from the socket, check for emergency shutdown, and
|
|
* sanity-check received bytes.
|
|
* The raw bytes read are stored in the sock_comm structure at
|
|
* comm->raw.
|
|
* The raw bytes are decoded and a xmit_t (header) struct pointer
|
|
* in comm is populated at comm->xmit_recd.
|
|
*
|
|
* Return: 0 on success, -1 if error.
|
|
* ---------------------------------------------------------------------------
|
|
*/
|
|
static int
|
|
receive_communique(struct mirror_session *session, struct sock_comm *comm)
|
|
{
|
|
ssize_t read_ret = 0;
|
|
size_t decode_ret;
|
|
H5FD_mirror_xmit_t *X = comm->xmit_recd;
|
|
|
|
HDassert((session != NULL) && (session->magic == MW_SESSION_MAGIC) && (comm != NULL) &&
|
|
(comm->magic == MW_SOCK_COMM_MAGIC) && (comm->xmit_recd != NULL) && (comm->raw != NULL) &&
|
|
(comm->raw_size >= H5FD_MIRROR_XMIT_BUFFER_MAX));
|
|
|
|
mirror_log(session->loginfo, V_INFO, "receive_communique()");
|
|
|
|
mybzero(comm->raw, comm->raw_size);
|
|
comm->recd_die = 0;
|
|
|
|
mirror_log(session->loginfo, V_INFO, "ready to receive"); /* TODO */
|
|
|
|
read_ret = HDread(session->sockfd, comm->raw, H5FD_MIRROR_XMIT_BUFFER_MAX);
|
|
if (-1 == read_ret) {
|
|
mirror_log(session->loginfo, V_ERR, "read:%zd", read_ret);
|
|
goto error;
|
|
}
|
|
|
|
mirror_log(session->loginfo, V_INFO, "received %zd bytes", read_ret);
|
|
if (HEXDUMP_XMITS) {
|
|
mirror_log(session->loginfo, V_ALL, "```", read_ret);
|
|
mirror_log_bytes(session->loginfo, V_ALL, (size_t)read_ret, (const unsigned char *)comm->raw);
|
|
mirror_log(session->loginfo, V_ALL, "```");
|
|
} /* end if hexdump transmissions received */
|
|
|
|
/* old-fashioned manual kill (for debugging) */
|
|
if (!HDstrncmp("GOODBYE", comm->raw, 7)) {
|
|
mirror_log(session->loginfo, V_INFO, "received GOODBYE");
|
|
comm->recd_die = 1;
|
|
goto done;
|
|
}
|
|
|
|
decode_ret = H5FD_mirror_xmit_decode_header(X, (const unsigned char *)comm->raw);
|
|
if (H5FD_MIRROR_XMIT_HEADER_SIZE != decode_ret) {
|
|
mirror_log(session->loginfo, V_ERR, "header decode size mismatch: expected (%z), got (%z)",
|
|
H5FD_MIRROR_XMIT_HEADER_SIZE, decode_ret);
|
|
/* Try to tell Driver that it should stop */
|
|
reply_error(session, "xmit size mismatch");
|
|
goto error;
|
|
}
|
|
|
|
if (!H5FD_mirror_xmit_is_xmit(X)) {
|
|
mirror_log(session->loginfo, V_ERR, "bad magic: 0x%X", X->magic);
|
|
/* Try to tell Driver that it should stop */
|
|
reply_error(session, "bad magic");
|
|
goto error;
|
|
}
|
|
|
|
if (session->xmit_count != X->xmit_count) {
|
|
mirror_log(session->loginfo, V_ERR, "xmit_count mismatch exp:%d recd:%d", session->xmit_count,
|
|
X->xmit_count);
|
|
/* Try to tell Driver that it should stop */
|
|
reply_error(session, "xmit_count mismatch");
|
|
goto error;
|
|
}
|
|
|
|
if ((session->token > 0) && (session->token != X->session_token)) {
|
|
mirror_log(session->loginfo, V_ERR, "wrong session");
|
|
/* Try to tell Driver that it should stop */
|
|
reply_error(session, "wrong session");
|
|
goto error;
|
|
}
|
|
|
|
session->xmit_count++;
|
|
|
|
done:
|
|
return 0;
|
|
|
|
error:
|
|
return -1;
|
|
} /* end receive_communique() */
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
* Function: process_instructions
|
|
*
|
|
* Purpose: Receive and handle all instructions from Driver.
|
|
*
|
|
* Return: 0 on success, -1 if error.
|
|
* ---------------------------------------------------------------------------
|
|
*/
|
|
static int
|
|
process_instructions(struct mirror_session *session)
|
|
{
|
|
struct sock_comm comm;
|
|
char xmit_buf[H5FD_MIRROR_XMIT_BUFFER_MAX]; /* raw bytes */
|
|
H5FD_mirror_xmit_t xmit_recd; /* for decoded xmit header */
|
|
|
|
HDassert(session && (session->magic == MW_SESSION_MAGIC));
|
|
|
|
mirror_log(session->loginfo, V_INFO, "process_instructions()");
|
|
|
|
comm.magic = MW_SOCK_COMM_MAGIC;
|
|
comm.recd_die = 0; /* Flag for program to terminate */
|
|
comm.xmit_recd = &xmit_recd;
|
|
comm.raw = xmit_buf;
|
|
comm.raw_size = sizeof(xmit_buf);
|
|
|
|
while (1) { /* sill-listening infinite loop */
|
|
|
|
/* Use convenience structure for raw/decoded info in/out */
|
|
if (receive_communique(session, &comm) < 0) {
|
|
mirror_log(session->loginfo, V_ERR, "problem reading socket");
|
|
return -1;
|
|
}
|
|
|
|
if (comm.recd_die) {
|
|
goto done;
|
|
}
|
|
|
|
switch (xmit_recd.op) {
|
|
case H5FD_MIRROR_OP_CLOSE:
|
|
if (do_close(session) < 0) {
|
|
return -1;
|
|
}
|
|
goto done;
|
|
case H5FD_MIRROR_OP_LOCK:
|
|
if (do_lock(session, (const unsigned char *)xmit_buf) < 0) {
|
|
return -1;
|
|
}
|
|
break;
|
|
case H5FD_MIRROR_OP_OPEN:
|
|
mirror_log(session->loginfo, V_ERR, "OPEN xmit during session");
|
|
reply_error(session, "illegal OPEN xmit during session");
|
|
return -1;
|
|
case H5FD_MIRROR_OP_SET_EOA:
|
|
if (do_set_eoa(session, (const unsigned char *)xmit_buf) < 0) {
|
|
return -1;
|
|
}
|
|
break;
|
|
case H5FD_MIRROR_OP_TRUNCATE:
|
|
if (do_truncate(session) < 0) {
|
|
return -1;
|
|
}
|
|
break;
|
|
case H5FD_MIRROR_OP_UNLOCK:
|
|
if (do_unlock(session) < 0) {
|
|
return -1;
|
|
}
|
|
break;
|
|
case H5FD_MIRROR_OP_WRITE:
|
|
if (do_write(session, (const unsigned char *)xmit_buf) < 0) {
|
|
return -1;
|
|
}
|
|
break;
|
|
default:
|
|
mirror_log(session->loginfo, V_ERR, "unrecognized transmission");
|
|
reply_error(session, "unrecognized transmission");
|
|
return -1;
|
|
} /* end switch (xmit_recd.op) */
|
|
|
|
} /* end while still listening */
|
|
|
|
done:
|
|
comm.magic = 0; /* invalidate structure, on principle */
|
|
xmit_recd.magic = 0; /* invalidate structure, on principle */
|
|
return 0;
|
|
} /* end process_instructions() */
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
* Function: run_writer
|
|
*
|
|
* Purpose: Initiate Writer operations.
|
|
*
|
|
* Receives as parameters a socket which has accepted the
|
|
* connection to the Driver and the OPEN xmit (which must be
|
|
* decoded into the structure and verified prior to being passed
|
|
* to this function).
|
|
*
|
|
* Is not responsible for closing or cleaning up any of the
|
|
* received parameters.
|
|
*
|
|
* Return: Success: SUCCEED
|
|
* Failure: FAIL
|
|
* ---------------------------------------------------------------------------
|
|
*/
|
|
herr_t
|
|
run_writer(int socketfd, H5FD_mirror_xmit_open_t *xmit_open)
|
|
{
|
|
struct mirror_session *session = NULL;
|
|
int ret_value = SUCCEED;
|
|
|
|
session = session_start(socketfd, xmit_open);
|
|
if (NULL == session) {
|
|
mirror_log(NULL, V_ERR, "Can't start session -- aborting");
|
|
ret_value = FAIL;
|
|
}
|
|
else {
|
|
if (process_instructions(session) < 0) {
|
|
mirror_log(session->loginfo, V_ERR, "problem processing instructions");
|
|
ret_value = FAIL;
|
|
}
|
|
if (session_stop(session) < 0) {
|
|
mirror_log(NULL, V_ERR, "Can't stop session -- going down hard");
|
|
ret_value = FAIL;
|
|
}
|
|
}
|
|
|
|
return ret_value;
|
|
} /* end run_writer */
|
|
|
|
#endif /* H5_HAVE_MIRROR_VFD */
|