diff options
Diffstat (limited to 'src/mercury/include/mercury_core.h')
-rw-r--r-- | src/mercury/include/mercury_core.h | 1074 |
1 files changed, 1074 insertions, 0 deletions
diff --git a/src/mercury/include/mercury_core.h b/src/mercury/include/mercury_core.h new file mode 100644 index 0000000..3d5c850 --- /dev/null +++ b/src/mercury/include/mercury_core.h @@ -0,0 +1,1074 @@ +/* + * Copyright (C) 2013-2020 Argonne National Laboratory, Department of Energy, + * UChicago Argonne, LLC and The HDF Group. + * All rights reserved. + * + * The full copyright notice, including terms governing use, modification, + * and redistribution, is contained in the COPYING file that can be + * found at the root of the source code distribution tree. + */ + +#ifndef MERCURY_CORE_H +#define MERCURY_CORE_H + +#include "mercury_core_header.h" +#include "mercury_core_types.h" + +#include "na.h" + +/*************************************/ +/* Public Type and Struct Definition */ +/*************************************/ + +typedef struct hg_core_class hg_core_class_t; /* Opaque HG core class */ +typedef struct hg_core_context hg_core_context_t; /* Opaque HG core context */ +typedef struct hg_core_addr * hg_core_addr_t; /* Abstract HG address */ +typedef struct hg_core_handle *hg_core_handle_t; /* Abstract RPC handle */ +typedef struct hg_core_op_id * hg_core_op_id_t; /* Abstract operation id */ + +/* HG info struct */ +struct hg_core_info { + hg_core_class_t * core_class; /* HG core class */ + hg_core_context_t *context; /* HG core context */ + hg_core_addr_t addr; /* HG address at target/origin */ + hg_id_t id; /* RPC ID */ + hg_uint8_t context_id; /* Context ID at target/origin */ +}; + +/* Callback info structs */ +struct hg_core_cb_info_lookup { + hg_core_addr_t addr; /* HG address */ +}; + +struct hg_core_cb_info_forward { + hg_core_handle_t handle; /* HG handle */ +}; + +struct hg_core_cb_info_respond { + hg_core_handle_t handle; /* HG handle */ +}; + +struct hg_core_cb_info { + union { /* Union of callback info structures */ + struct hg_core_cb_info_lookup lookup; + struct hg_core_cb_info_forward forward; + struct hg_core_cb_info_respond respond; + } info; + void * arg; /* User data */ + hg_cb_type_t type; /* Callback type */ + hg_return_t ret; /* Return value */ +}; + +/* RPC / HG callbacks */ +typedef hg_return_t (*hg_core_rpc_cb_t)(hg_core_handle_t handle); +typedef hg_return_t (*hg_core_cb_t)(const struct hg_core_cb_info *callback_info); + +/*****************/ +/* Public Macros */ +/*****************/ + +/* Constant values */ +#define HG_CORE_ADDR_NULL ((hg_core_addr_t)0) +#define HG_CORE_HANDLE_NULL ((hg_core_handle_t)0) +#define HG_CORE_OP_ID_NULL ((hg_core_op_id_t)0) +#define HG_CORE_OP_ID_IGNORE ((hg_core_op_id_t *)1) + +/* Flags */ +#define HG_CORE_MORE_DATA (1 << 0) /* More data required */ +#define HG_CORE_NO_RESPONSE (1 << 1) /* No response required */ + +/*********************/ +/* Public Prototypes */ +/*********************/ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Initialize the core Mercury layer. + * Must be finalized with HG_Core_finalize(). + * + * \param na_info_string [IN] host address with port number (e.g., + * "tcp://localhost:3344" or + * "bmi+tcp://localhost:3344") + * \param na_listen [IN] listen for incoming connections + * + * \return Pointer to HG core class or NULL in case of failure + */ +HG_PUBLIC hg_core_class_t *HG_Core_init(const char *na_info_string, hg_bool_t na_listen); + +/** + * Initialize the Mercury layer with options provided by init_info. + * Must be finalized with HG_Core_finalize(). + * \remark HG_Core_init_opt() may become HG_Core_init() in the future. + * + * \param na_info_string [IN] host address with port number (e.g., + * "tcp://localhost:3344" or + * "bmi+tcp://localhost:3344") + * \param na_listen [IN] listen for incoming connections + * \param hg_init_info [IN] (Optional) HG init info, NULL if no info + * + * \return Pointer to HG core class or NULL in case of failure + */ +HG_PUBLIC hg_core_class_t *HG_Core_init_opt(const char *na_info_string, hg_bool_t na_listen, + const struct hg_init_info *hg_init_info); + +/** + * Finalize the Mercury layer. + * + * \param hg_core_class [IN] pointer to HG core class + * + * \return HG_SUCCESS or corresponding HG error code + */ +HG_PUBLIC hg_return_t HG_Core_finalize(hg_core_class_t *hg_core_class); + +/** + * Clean up all temporary files that were created in previous HG instances. + * While temporary resources (e.g., tmp files) are cleaned up on a call + * to HG_Finalize(), this routine gives a chance to programs that terminate + * abnormally to easily clean up those resources. + */ +HG_PUBLIC void HG_Core_cleanup(void); + +/** + * Set callback that will be triggered when additional data needs to be + * transferred and HG_Core_set_more_data() has been called, usually when the + * eager message size is exceeded. This allows upper layers to manually transfer + * data using bulk transfers for example. The done_callback argument allows the + * upper layer to notify back once the data has been successfully acquired. + * The release callback allows the upper layer to release resources that were + * allocated when acquiring the data. + * + * \param hg_core_class [IN] pointer to HG core class + * \param more_data_acquire_callback [IN] pointer to acquire function callback + * \param more_data_release_callback [IN] pointer to release function callback + * + * \return HG_SUCCESS or corresponding HG error code + */ +HG_PUBLIC hg_return_t HG_Core_set_more_data_callback( + struct hg_core_class *hg_core_class, + hg_return_t (*more_data_acquire_callback)(hg_core_handle_t, hg_op_t, + hg_return_t (*done_callback)(hg_core_handle_t)), + void (*more_data_release_callback)(hg_core_handle_t)); + +/** + * Obtain the name of the given class. + * + * \param hg_core_class [IN] pointer to HG core class + * + * \return the name of the class, or NULL if not a valid class + */ +static HG_INLINE const char *HG_Core_class_get_name(const hg_core_class_t *hg_core_class); + +/** + * Obtain the protocol of the given class. + * + * \param hg_core_class [IN] pointer to HG core class + * + * \return the protocol of the class, or NULL if not a valid class + */ +static HG_INLINE const char *HG_Core_class_get_protocol(const hg_core_class_t *hg_core_class); + +/** + * Test whether class is listening or not. + * + * \param hg_core_class [IN] pointer to HG core class + * + * \return HG_TRUE if listening or HG_FALSE if not, or not a valid class + */ +static HG_INLINE hg_bool_t HG_Core_class_is_listening(const hg_core_class_t *hg_core_class); + +/** + * Obtain the underlying NA class. + * + * \param hg_core_class [IN] pointer to HG core class + * + * \return Pointer to NA class or NULL if not a valid class + */ +static HG_INLINE na_class_t *HG_Core_class_get_na(const hg_core_class_t *hg_core_class); + +#ifdef NA_HAS_SM +/** + * Obtain the underlying NA SM class. + * + * \param hg_core_class [IN] pointer to HG core class + * + * \return Pointer to NA SM class or NULL if not a valid class + */ +static HG_INLINE na_class_t *HG_Core_class_get_na_sm(const hg_core_class_t *hg_core_class); +#endif + +/** + * Obtain the maximum eager size for sending RPC inputs. + * + * \param hg_core_class [IN] pointer to HG core class + * + * \return the maximum size, or 0 if hg_core_class is not a valid class or + * XDR is being used + */ +static HG_INLINE hg_size_t HG_Core_class_get_input_eager_size(const hg_core_class_t *hg_core_class); + +/** + * Obtain the maximum eager size for sending RPC outputs. + * + * \param hg_core_class [IN] pointer to HG core class + * + * \return the maximum size, or 0 if hg_core_class is not a valid class or XDR + * is being used + */ +static HG_INLINE hg_size_t HG_Core_class_get_output_eager_size(const hg_core_class_t *hg_core_class); + +/** + * Associate user data to class. When HG_Core_finalize() is called, + * free_callback (if defined) is called to free the associated data. + * + * \param hg_core_class [IN] pointer to HG core class + * \param data [IN] pointer to user data + * \param free_callback [IN] pointer to function + * + * \return HG_SUCCESS or corresponding HG error code + */ +static HG_INLINE hg_return_t HG_Core_class_set_data(hg_core_class_t *hg_core_class, void *data, + void (*free_callback)(void *)); + +/** + * Retrieve previously associated data from a given class. + * + * \param hg_core_class [IN] pointer to HG core class + * + * \return Pointer to user data or NULL if not set or any error has occurred + */ +static HG_INLINE void *HG_Core_class_get_data(const hg_core_class_t *hg_core_class); + +/** + * Create a new context. Must be destroyed by calling HG_Core_context_destroy(). + * + * \param hg_core_class [IN] pointer to HG core class + * + * \return Pointer to HG core context or NULL in case of failure + */ +HG_PUBLIC hg_core_context_t *HG_Core_context_create(hg_core_class_t *hg_core_class); + +/** + * Create a new context with a user-defined context identifier. The context + * identifier can be used to route RPC requests to specific contexts by using + * HG_Core_set_target_id(). + * Context must be destroyed by calling HG_Core_context_destroy(). + * + * \param hg_core_class [IN] pointer to HG core class + * \param id [IN] context ID + * + * \return Pointer to HG core context or NULL in case of failure + */ +HG_PUBLIC hg_core_context_t *HG_Core_context_create_id(hg_core_class_t *hg_core_class, hg_uint8_t id); + +/** + * Destroy a context created by HG_Core_context_create(). + * + * \param context [IN] pointer to HG core context + * + * \return HG_SUCCESS or corresponding HG error code + */ +HG_PUBLIC hg_return_t HG_Core_context_destroy(hg_core_context_t *context); + +/** + * Retrieve the class used to create the given context. + * + * \param context [IN] pointer to HG core context + * + * \return the associated class + */ +static HG_INLINE hg_core_class_t *HG_Core_context_get_class(const hg_core_context_t *context); + +/** + * Retrieve the underlying NA context. + * + * \param context [IN] pointer to HG core context + * + * \return the associated context + */ +static HG_INLINE na_context_t *HG_Core_context_get_na(const hg_core_context_t *context); + +#ifdef NA_HAS_SM +/** + * Retrieve the underlying NA SM context. + * + * \param context [IN] pointer to HG core context + * + * \return the associated context + */ +static HG_INLINE na_context_t *HG_Core_context_get_na_sm(const hg_core_context_t *context); +#endif + +/** + * Retrieve context ID from context. + * + * \param context [IN] pointer to HG core context + * + * \return Non-negative integer (max value of 255) or 0 if no ID has been set + */ +static HG_INLINE hg_uint8_t HG_Core_context_get_id(const hg_core_context_t *context); + +/** + * Associate user data to context. When HG_Core_context_destroy() is called, + * free_callback (if defined) is called to free the associated data. + * + * \param context [IN] pointer to HG core context + * \param data [IN] pointer to user data + * \param free_callback [IN] pointer to function + * + * \return HG_SUCCESS or corresponding HG error code + */ +static HG_INLINE hg_return_t HG_Core_context_set_data(hg_core_context_t *context, void *data, + void (*free_callback)(void *)); + +/** + * Retrieve previously associated data from a given context. + * + * \param context [IN] pointer to HG core context + * + * \return Pointer to user data or NULL if not set or any error has occurred + */ +static HG_INLINE void *HG_Core_context_get_data(const hg_core_context_t *context); + +/** + * Set callback to be called on HG core handle creation. Handles are created + * both on HG_Core_create() and HG_Core_context_post() calls. This allows + * upper layers to create and attach data to a handle (using HG_Core_set_data()) + * and later retrieve it using HG_Core_get_data(). + * + * \param context [IN] pointer to HG core context + * \param callback [IN] pointer to function callback + * \param arg [IN] pointer to data passed to callback + * + * \return HG_SUCCESS or corresponding HG error code + */ +HG_PUBLIC hg_return_t HG_Core_context_set_handle_create_callback( + hg_core_context_t *context, hg_return_t (*callback)(hg_core_handle_t, void *), void *arg); + +/** + * Post requests associated to context in order to receive incoming RPCs. + * Requests are automatically re-posted after completion until the context is + * destroyed. Additionally a callback can be triggered on HG handle + * creation. This allows upper layers to instantiate data that needs to be + * attached to a handle. Number of requests that are posted can be controlled + * through HG init info. + * + * \param context [IN] pointer to HG core context + * + * \return the associated class + */ +HG_PUBLIC hg_return_t HG_Core_context_post(hg_core_context_t *context); + +/** + * Dynamically register an RPC ID as well as the RPC callback executed + * when the RPC request ID is received. + * + * \param hg_core_class [IN] pointer to HG core class + * \param id [IN] ID to use to register RPC + * \param rpc_cb [IN] RPC callback + * + * \return HG_SUCCESS or corresponding HG error code + */ +HG_PUBLIC hg_return_t HG_Core_register(hg_core_class_t *hg_core_class, hg_id_t id, hg_core_rpc_cb_t rpc_cb); + +/** + * Deregister RPC ID. Further requests with RPC ID will return an error, it + * is therefore up to the user to make sure that all requests for that RPC ID + * have been treated before it is unregistered. + * + * \param hg_core_class [IN] pointer to HG core class + * \param id [IN] registered function ID + * + * \return HG_SUCCESS or corresponding HG error code + */ +HG_PUBLIC hg_return_t HG_Core_deregister(hg_core_class_t *hg_core_class, hg_id_t id); + +/** + * Indicate whether HG_Core_register() has been called. + * + * \param hg_core_class [IN] pointer to HG core class + * \param id [IN] function ID + * \param flag [OUT] pointer to boolean + * + * \return HG_SUCCESS or corresponding HG error code + */ +HG_PUBLIC hg_return_t HG_Core_registered(hg_core_class_t *hg_core_class, hg_id_t id, hg_bool_t *flag); + +/** + * Register and associate user data to registered function. When + * HG_Core_finalize() is called, free_callback (if defined) is called to free + * the registered data. + * + * \param hg_core_class [IN] pointer to HG core class + * \param id [IN] registered function ID + * \param data [IN] pointer to data + * \param free_callback [IN] pointer to function + * + * \return HG_SUCCESS or corresponding HG error code + */ +HG_PUBLIC hg_return_t HG_Core_register_data(hg_core_class_t *hg_core_class, hg_id_t id, void *data, + void (*free_callback)(void *)); + +/** + * Indicate whether HG_Core_register_data() has been called and return + * associated data. + * + * \param hg_core_class [IN] pointer to HG core class + * \param id [IN] registered function ID + * + * \return Pointer to data or NULL + */ +HG_PUBLIC void *HG_Core_registered_data(hg_core_class_t *hg_core_class, hg_id_t id); + +/** + * Lookup an addr from a peer address/name. Addresses need to be + * freed by calling HG_Core_addr_free(). After completion, user callback is + * placed into a completion queue and can be triggered using HG_Core_trigger(). + * + * \param context [IN] pointer to context of execution + * \param callback [IN] pointer to function callback + * \param arg [IN] pointer to data passed to callback + * \param name [IN] lookup name + * \param op_id [OUT] pointer to returned operation ID (unused) + * + * \return HG_SUCCESS or corresponding HG error code + */ +HG_PUBLIC hg_return_t HG_Core_addr_lookup1(hg_core_context_t *context, hg_core_cb_t callback, void *arg, + const char *name, hg_core_op_id_t *op_id); + +/** + * Lookup an addr from a peer address/name. Addresses need to be + * freed by calling HG_Core_addr_free(). + * + * \param hg_core_class [IN] pointer to HG core class + * \param name [IN] lookup name + * \param addr [OUT] pointer to abstract address + * + * \return HG_SUCCESS or corresponding HG error code + */ +HG_PUBLIC hg_return_t HG_Core_addr_lookup2(hg_core_class_t *hg_core_class, const char *name, + hg_core_addr_t *addr); + +/** + * Free the addr from the list of peers. + * + * \param addr [IN] abstract address + * + * \return HG_SUCCESS or corresponding HG error code + */ +HG_PUBLIC hg_return_t HG_Core_addr_free(hg_core_addr_t addr); + +/** + * Hint that the address is no longer valid. This may happen if the peer is + * no longer responding. This can be used to force removal of the + * peer address from the list of the peers, before freeing it and reclaim + * resources. + * + * \param addr [IN] abstract address + * + * \return HG_SUCCESS or corresponding HG error code + */ +HG_PUBLIC hg_return_t HG_Core_addr_set_remove(hg_core_addr_t addr); + +/** + * Obtain the underlying NA address from an HG address. + * + * \param addr [IN] abstract address + * + * \return abstract NA addr or NA_ADDR_NULL if not a valid HG address + */ +static HG_INLINE na_addr_t HG_Core_addr_get_na(hg_core_addr_t addr); + +#ifdef NA_HAS_SM +/** + * Obtain the underlying NA SM address from an HG address. + * + * \param addr [IN] abstract address + * + * \return abstract NA addr or NA_ADDR_NULL if not a valid HG address + */ +static HG_INLINE na_addr_t HG_Core_addr_get_na_sm(hg_core_addr_t addr); +#endif + +/** + * Access self address. Address must be freed with HG_Core_addr_free(). + * + * \param hg_core_class [IN] pointer to HG core class + * \param addr [OUT] pointer to abstract address + * + * \return HG_SUCCESS or corresponding HG error code + */ +HG_PUBLIC hg_return_t HG_Core_addr_self(hg_core_class_t *hg_core_class, hg_core_addr_t *addr); + +/** + * Duplicate an existing HG abstract address. The duplicated address can be + * stored for later use and the origin address be freed safely. The duplicated + * address must be freed with HG_Core_addr_free(). + * + * \param addr [IN] abstract address + * \param new_addr [OUT] pointer to abstract address + * + * \return HG_SUCCESS or corresponding HG error code + */ +HG_PUBLIC hg_return_t HG_Core_addr_dup(hg_core_addr_t addr, hg_core_addr_t *new_addr); + +/** + * Compare two addresses. + * + * \param addr1 [IN] abstract address + * \param addr2 [IN] abstract address + * + * \return HG_TRUE if addresses are determined to be equal, HG_FALSE otherwise + */ +HG_PUBLIC hg_bool_t HG_Core_addr_cmp(hg_core_addr_t addr1, hg_core_addr_t addr2); + +/** + * Test whether address is self or not. + * + * \param addr [IN] pointer to abstract address + * + * \return HG_TRUE if address is self address, HG_FALSE otherwise + */ +static HG_INLINE hg_bool_t HG_Core_addr_is_self(hg_core_addr_t addr); + +/** + * Convert an addr to a string (returned string includes the terminating + * null byte '\0'). If buf is NULL, the address is not converted and only + * the required size of the buffer is returned. If the input value passed + * through buf_size is too small, HG_SIZE_ERROR is returned and the buf_size + * output is set to the minimum size required. + * + * \param buf [IN/OUT] pointer to destination buffer + * \param buf_size [IN/OUT] pointer to buffer size + * \param addr [IN] abstract address + * + * \return HG_SUCCESS or corresponding HG error code + */ +HG_PUBLIC hg_return_t HG_Core_addr_to_string(char *buf, hg_size_t *buf_size, hg_core_addr_t addr); + +/** + * Get size required to serialize address. + * + * \param addr [IN] abstract address + * \param flags [IN] optional flags + * + * \return Non-negative value + */ +HG_PUBLIC hg_size_t HG_Core_addr_get_serialize_size(hg_core_addr_t addr, unsigned long flags); + +/** + * Serialize address into a buffer. + * + * \param buf [IN/OUT] pointer to destination buffer + * \param buf_size [IN] pointer to buffer size + * \param flags [IN] optional flags + * \param addr [IN] abstract address + * + * \return HG_SUCCESS or corresponding HG error code + */ +HG_PUBLIC hg_return_t HG_Core_addr_serialize(void *buf, hg_size_t buf_size, unsigned long flags, + hg_core_addr_t addr); + +/** + * Deserialize address from a buffer. The returned address must be freed with + * HG_Core_addr_free(). + * + * \param hg_core_class [IN] pointer to HG core class + * \param addr [OUT] pointer to abstract address + * \param buf [IN] pointer to buffer used for deserialization + * \param buf_size [IN] buffer size + * + * \return HG_SUCCESS or corresponding HG error code + */ +HG_PUBLIC hg_return_t HG_Core_addr_deserialize(hg_core_class_t *hg_core_class, hg_core_addr_t *addr, + const void *buf, hg_size_t buf_size); + +/** + * Initiate a new HG RPC using the specified function ID and the local/remote + * target defined by addr. The HG handle created can be used to query input + * and output buffers, as well as issuing the RPC by using HG_Core_forward(). + * After completion the handle must be freed using HG_Core_destroy(). + * + * \param context [IN] pointer to HG core context + * \param addr [IN] target address + * \param id [IN] registered function ID + * \param handle [OUT] pointer to HG handle + * + * \return HG_SUCCESS or corresponding HG error code + */ +HG_PUBLIC hg_return_t HG_Core_create(hg_core_context_t *context, hg_core_addr_t addr, hg_id_t id, + hg_core_handle_t *handle); + +/** + * Destroy HG handle. Decrement reference count, resources associated to the + * handle are freed when the reference count is null. + * + * \param handle [IN] HG handle + * + * \return HG_SUCCESS or corresponding HG error code + */ +HG_PUBLIC hg_return_t HG_Core_destroy(hg_core_handle_t handle); + +/** + * Reset an existing HG handle to make it reusable for RPC forwarding. + * Both target address and RPC ID can be modified at this time. + * Operations on that handle must be completed in order to reset that handle + * safely. + * + * \param handle [IN] HG handle + * \param addr [IN] abstract network address of destination + * \param id [IN] registered function ID + * + * \return HG_SUCCESS or corresponding HG error code + */ +HG_PUBLIC hg_return_t HG_Core_reset(hg_core_handle_t handle, hg_core_addr_t addr, hg_id_t id); + +/** + * Increment ref count on handle. + * + * \param handle [IN] HG handle + * + * \return HG_SUCCESS or corresponding HG error code + */ +HG_PUBLIC hg_return_t HG_Core_ref_incr(hg_core_handle_t handle); + +/** + * Retrieve ref count from handle. + * + * \param handle [IN] HG handle + * + * \return Non-negative value or negative if the handle is not valid + */ +HG_PUBLIC hg_int32_t HG_Core_ref_get(hg_core_handle_t handle); + +/** + * Allows upper layers to attach data to an existing HG handle. + * The free_callback argument allows allocated resources to be released when + * the handle gets freed. + * + * \param handle [IN] HG handle + * \param data [IN] pointer to user data + * \param free_callback pointer to free function callback + * + * \return HG_SUCCESS or corresponding HG error code + */ +static HG_INLINE hg_return_t HG_Core_set_data(hg_core_handle_t handle, void *data, + void (*free_callback)(void *)); + +/** + * Allows upper layers to retrieve data from an existing HG handle. + * Only valid if HG_Core_set_data() has been previously called. + * + * \param handle [IN] HG handle + * + * \return Pointer to user data or NULL if not set or any error has occurred + */ +static HG_INLINE void *HG_Core_get_data(hg_core_handle_t handle); + +/** + * Get info from handle. + * + * \remark Users must call HG_Core_addr_dup() to safely re-use the addr field. + * + * \param handle [IN] HG handle + * + * \return Pointer to info or NULL in case of failure + */ +static HG_INLINE const struct hg_core_info *HG_Core_get_info(hg_core_handle_t handle); + +/** + * Allows upper layers to retrieve cached RPC data from an existing HG handle. + * Only valid if HG_Core_register_data() has been previously called. + * + * \param handle [IN] HG handle + * + * \return Pointer to user data or NULL if not set or any error has occurred + */ +static HG_INLINE const void *HG_Core_get_rpc_data(hg_core_handle_t handle); + +/** + * Set target context ID that will receive and process the RPC request + * (ID is defined on target context creation, see HG_Core_context_create_id()). + * + * \param handle [IN] HG handle + * \param id [IN] user-defined target context ID + * + * \return HG_SUCCESS or corresponding HG error code + */ +static HG_INLINE hg_return_t HG_Core_set_target_id(hg_core_handle_t handle, hg_uint8_t id); + +/** + * Get input buffer from handle that can be used for serializing/deserializing + * parameters. + * + * \param handle [IN] HG handle + * \param in_buf [OUT] pointer to input buffer + * \param in_buf_size [OUT] pointer to input buffer size + * + * \return HG_SUCCESS or corresponding HG error code + */ +static HG_INLINE hg_return_t HG_Core_get_input(hg_core_handle_t handle, void **in_buf, + hg_size_t *in_buf_size); + +/** + * Get output buffer from handle that can be used for serializing/deserializing + * parameters. + * + * \param handle [IN] HG handle + * \param out_buf [OUT] pointer to output buffer + * \param out_buf_size [OUT] pointer to output buffer size + * + * \return HG_SUCCESS or corresponding HG error code + */ +static HG_INLINE hg_return_t HG_Core_get_output(hg_core_handle_t handle, void **out_buf, + hg_size_t *out_buf_size); + +/** + * Forward a call using an existing HG handle. Input and output buffers can be + * queried from the handle to serialize/deserialize parameters. + * Additionally, a bulk handle can be passed if the size of the input is larger + * than the queried input buffer size. + * After completion, the handle must be freed using HG_Core_destroy(), the user + * callback is placed into a completion queue and can be triggered using + * HG_Core_trigger(). + * + * \param handle [IN] HG handle + * \param callback [IN] pointer to function callback + * \param arg [IN] pointer to data passed to callback + * \param payload_size [IN] size of payload to send + * + * \return HG_SUCCESS or corresponding HG error code + */ +HG_PUBLIC hg_return_t HG_Core_forward(hg_core_handle_t handle, hg_core_cb_t callback, void *arg, + hg_uint8_t flags, hg_size_t payload_size); + +/** + * Respond back to the origin. The output buffer, which can be used to encode + * the response, must first be queried using HG_Core_get_output(). + * After completion, the user callback is placed into a completion queue and + * can be triggered using HG_Core_trigger(). + * + * \param handle [IN] HG handle + * \param callback [IN] pointer to function callback + * \param arg [IN] pointer to data passed to callback + * \param payload_size [IN] size of payload to send + * + * \return HG_SUCCESS or corresponding HG error code + */ +HG_PUBLIC hg_return_t HG_Core_respond(hg_core_handle_t handle, hg_core_cb_t callback, void *arg, + hg_uint8_t flags, hg_size_t payload_size); + +/** + * Try to progress RPC execution for at most timeout until timeout is reached or + * any completion has occurred. + * Progress should not be considered as wait, in the sense that it cannot be + * assumed that completion of a specific operation will occur only when + * progress is called. + * + * \param context [IN] pointer to HG core context + * \param timeout [IN] timeout (in milliseconds) + * + * \return HG_SUCCESS if any completion has occurred / HG error code otherwise + */ +HG_PUBLIC hg_return_t HG_Core_progress(hg_core_context_t *context, unsigned int timeout); + +/** + * Execute at most max_count callbacks. If timeout is non-zero, wait up to + * timeout before returning. Function can return when at least one or more + * callbacks are triggered (at most max_count). + * + * \param context [IN] pointer to HG core context + * \param timeout [IN] timeout (in milliseconds) + * \param max_count [IN] maximum number of callbacks triggered + * \param actual_count [IN] actual number of callbacks triggered + * + * \return HG_SUCCESS or corresponding HG error code + */ +HG_PUBLIC hg_return_t HG_Core_trigger(hg_core_context_t *context, unsigned int timeout, + unsigned int max_count, unsigned int *actual_count); + +/** + * Cancel an ongoing operation. + * + * \param handle [IN] HG handle + * + * \return HG_SUCCESS or corresponding HG error code + */ +HG_PUBLIC hg_return_t HG_Core_cancel(hg_core_handle_t handle); + +/************************************/ +/* Local Type and Struct Definition */ +/************************************/ + +/* HG core class */ +struct hg_core_class { + na_class_t *na_class; /* NA class */ +#ifdef NA_HAS_SM + na_class_t *na_sm_class; /* NA SM class */ +#endif + void *data; /* User data */ + void (*data_free_callback)(void *); /* User data free callback */ +}; + +/* HG core context */ +struct hg_core_context { + struct hg_core_class *core_class; /* HG core class */ + na_context_t * na_context; /* NA context */ +#ifdef NA_HAS_SM + na_context_t *na_sm_context; /* NA SM context */ +#endif + void *data; /* User data */ + void (*data_free_callback)(void *); /* User data free callback */ + hg_uint8_t id; /* Context ID */ +}; + +/* HG core addr */ +struct hg_core_addr { + struct hg_core_class *core_class; /* HG core class */ + na_addr_t na_addr; /* NA address */ +#ifdef NA_HAS_SM + na_addr_t na_sm_addr; /* NA SM address */ +#endif + hg_bool_t is_self; /* Self address */ +}; + +/* HG core RPC registration info */ +struct hg_core_rpc_info { + hg_core_rpc_cb_t rpc_cb; /* RPC callback */ + void * data; /* User data */ + void (*free_callback)(void *); /* User data free callback */ +}; + +/* HG core handle */ +struct hg_core_handle { + struct hg_core_info info; /* HG info */ + struct hg_core_rpc_info *rpc_info; /* Associated RPC registration info */ + void * data; /* User data */ + void (*data_free_callback)(void *); /* User data free callback */ + void * in_buf; /* Input buffer */ + void * out_buf; /* Output buffer */ + na_size_t in_buf_size; /* Input buffer size */ + na_size_t out_buf_size; /* Output buffer size */ + na_size_t na_in_header_offset; /* Input NA header offset */ + na_size_t na_out_header_offset; /* Output NA header offset */ +}; + +/*---------------------------------------------------------------------------*/ +static HG_INLINE const char * +HG_Core_class_get_name(const hg_core_class_t *hg_core_class) +{ + return NA_Get_class_name(hg_core_class->na_class); +} + +/*---------------------------------------------------------------------------*/ +static HG_INLINE const char * +HG_Core_class_get_protocol(const hg_core_class_t *hg_core_class) +{ + return NA_Get_class_protocol(hg_core_class->na_class); +} + +/*---------------------------------------------------------------------------*/ +static HG_INLINE hg_bool_t +HG_Core_class_is_listening(const hg_core_class_t *hg_core_class) +{ + return NA_Is_listening(hg_core_class->na_class); +} + +/*---------------------------------------------------------------------------*/ +static HG_INLINE na_class_t * + HG_Core_class_get_na(const hg_core_class_t *hg_core_class) +{ + return hg_core_class->na_class; +} + +/*---------------------------------------------------------------------------*/ +#ifdef NA_HAS_SM +static HG_INLINE na_class_t * + HG_Core_class_get_na_sm(const hg_core_class_t *hg_core_class) +{ + return hg_core_class->na_sm_class; +} +#endif + +/*---------------------------------------------------------------------------*/ +static HG_INLINE hg_size_t +HG_Core_class_get_input_eager_size(const hg_core_class_t *hg_core_class) +{ + hg_size_t unexp = NA_Msg_get_max_unexpected_size(hg_core_class->na_class), + header = hg_core_header_request_get_size() + + NA_Msg_get_unexpected_header_size(hg_core_class->na_class); + + return (unexp > header) ? unexp - header : 0; +} + +/*---------------------------------------------------------------------------*/ +static HG_INLINE hg_size_t +HG_Core_class_get_output_eager_size(const hg_core_class_t *hg_core_class) +{ + hg_size_t exp = NA_Msg_get_max_expected_size(hg_core_class->na_class), + header = hg_core_header_response_get_size() + + NA_Msg_get_expected_header_size(hg_core_class->na_class); + + return (exp > header) ? exp - header : 0; +} + +/*---------------------------------------------------------------------------*/ +static HG_INLINE hg_return_t +HG_Core_class_set_data(hg_core_class_t *hg_core_class, void *data, void (*free_callback)(void *)) +{ + hg_core_class->data = data; + hg_core_class->data_free_callback = free_callback; + + return HG_SUCCESS; +} + +/*---------------------------------------------------------------------------*/ +static HG_INLINE void * +HG_Core_class_get_data(const hg_core_class_t *hg_core_class) +{ + return hg_core_class->data; +} + +/*---------------------------------------------------------------------------*/ +static HG_INLINE hg_core_class_t * + HG_Core_context_get_class(const hg_core_context_t *context) +{ + return context->core_class; +} + +/*---------------------------------------------------------------------------*/ +static HG_INLINE na_context_t * + HG_Core_context_get_na(const hg_core_context_t *context) +{ + return context->na_context; +} + +/*---------------------------------------------------------------------------*/ +#ifdef NA_HAS_SM +static HG_INLINE na_context_t * + HG_Core_context_get_na_sm(const hg_core_context_t *context) +{ + return context->na_sm_context; +} +#endif + +/*---------------------------------------------------------------------------*/ +static HG_INLINE hg_uint8_t +HG_Core_context_get_id(const hg_core_context_t *context) +{ + return context->id; +} + +/*---------------------------------------------------------------------------*/ +static HG_INLINE hg_return_t +HG_Core_context_set_data(hg_core_context_t *context, void *data, void (*free_callback)(void *)) +{ + context->data = data; + context->data_free_callback = free_callback; + + return HG_SUCCESS; +} + +/*---------------------------------------------------------------------------*/ +static HG_INLINE void * +HG_Core_context_get_data(const hg_core_context_t *context) +{ + return context->data; +} + +/*---------------------------------------------------------------------------*/ +static HG_INLINE na_addr_t +HG_Core_addr_get_na(hg_core_addr_t addr) +{ + return addr->na_addr; +} + +/*---------------------------------------------------------------------------*/ +#ifdef NA_HAS_SM +static HG_INLINE na_addr_t +HG_Core_addr_get_na_sm(hg_core_addr_t addr) +{ + return addr->na_sm_addr; +} +#endif + +/*---------------------------------------------------------------------------*/ +static HG_INLINE hg_bool_t +HG_Core_addr_is_self(hg_core_addr_t addr) +{ + return addr->is_self; +} + +/*---------------------------------------------------------------------------*/ +static HG_INLINE hg_return_t +HG_Core_set_data(hg_core_handle_t handle, void *data, void (*free_callback)(void *)) +{ + handle->data = data; + handle->data_free_callback = free_callback; + + return HG_SUCCESS; +} + +/*---------------------------------------------------------------------------*/ +static HG_INLINE void * +HG_Core_get_data(hg_core_handle_t handle) +{ + return handle->data; +} + +/*---------------------------------------------------------------------------*/ +static HG_INLINE const struct hg_core_info * +HG_Core_get_info(hg_core_handle_t handle) +{ + return &handle->info; +} + +/*---------------------------------------------------------------------------*/ +static HG_INLINE const void * +HG_Core_get_rpc_data(hg_core_handle_t handle) +{ + return (handle->rpc_info) ? handle->rpc_info->data : NULL; +} + +/*---------------------------------------------------------------------------*/ +static HG_INLINE hg_return_t +HG_Core_set_target_id(hg_core_handle_t handle, hg_uint8_t id) +{ + handle->info.context_id = id; + + return HG_SUCCESS; +} + +/*---------------------------------------------------------------------------*/ +static HG_INLINE hg_return_t +HG_Core_get_input(hg_core_handle_t handle, void **in_buf, hg_size_t *in_buf_size) +{ + hg_size_t header_offset = hg_core_header_request_get_size() + handle->na_in_header_offset; + + /* Space must be left for request header */ + *in_buf = (char *)handle->in_buf + header_offset; + *in_buf_size = handle->in_buf_size - header_offset; + + return HG_SUCCESS; +} + +/*---------------------------------------------------------------------------*/ +static HG_INLINE hg_return_t +HG_Core_get_output(hg_core_handle_t handle, void **out_buf, hg_size_t *out_buf_size) +{ + hg_size_t header_offset = hg_core_header_response_get_size() + handle->na_out_header_offset; + + /* Space must be left for response header */ + *out_buf = (char *)handle->out_buf + header_offset; + *out_buf_size = handle->out_buf_size - header_offset; + + return HG_SUCCESS; +} + +#ifdef __cplusplus +} +#endif + +#endif /* MERCURY_CORE_H */ |