diff options
Diffstat (limited to 'src/mercury/include/na.h')
-rw-r--r-- | src/mercury/include/na.h | 1064 |
1 files changed, 1064 insertions, 0 deletions
diff --git a/src/mercury/include/na.h b/src/mercury/include/na.h new file mode 100644 index 0000000..88b97f8 --- /dev/null +++ b/src/mercury/include/na.h @@ -0,0 +1,1064 @@ +/* + * 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 NA_H +#define NA_H + +#include "na_types.h" + +/*************************************/ +/* Public Type and Struct Definition */ +/*************************************/ + +/* See na_types.h */ + +/*****************/ +/* Public Macros */ +/*****************/ + +/* See na_types.h */ + +/*********************/ +/* Public Prototypes */ +/*********************/ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Initialize the network abstraction layer. + * Must be finalized with NA_Finalize(). + * + * \param info_string [IN] host address with port number (e.g., + * "tcp://localhost:3344" or + * "bmi+tcp://localhost:3344") + * \param listen [IN] listen for incoming connections + * + * \return Pointer to NA class or NULL in case of failure + */ +NA_PUBLIC na_class_t *NA_Initialize(const char *info_string, na_bool_t listen) NA_WARN_UNUSED_RESULT; + +/** + * Initialize the network abstraction layer with options provided by init_info. + * Must be finalized with NA_Finalize(). + * + * \param info_string [IN] host address with port number (e.g., + * "tcp://localhost:3344" or + * "bmi+tcp://localhost:3344") + * \param listen [IN] listen for incoming connections + * \param na_init_info [IN] (Optional) NA init info, NULL if no info + * + * \return Pointer to NA class or NULL in case of failure + */ +NA_PUBLIC na_class_t *NA_Initialize_opt(const char *info_string, na_bool_t listen, + const struct na_init_info *na_init_info) NA_WARN_UNUSED_RESULT; + +/** + * Finalize the network abstraction layer. + * + * \param na_class [IN/OUT] pointer to NA class + * + * \return NA_SUCCESS or corresponding NA error code + */ +NA_PUBLIC na_return_t NA_Finalize(na_class_t *na_class); + +/** + * Clean up all temporary files that were created in previous NA instances. + * While temporary resources (e.g., tmp files) are cleaned up on a call + * to NA_Finalize(), this routine gives a chance to programs that terminate + * abnormally to easily clean up those resources. This includes instances + * from all plugins. + */ +NA_PUBLIC void NA_Cleanup(void); + +/** + * Set the log level for NA. That setting is valid for all NA classes. + * + * \param level [IN] level string, valid values are: + * "none", "error", "warning", "debug" + */ +NA_PUBLIC void NA_Set_log_level(const char *level); + +/** + * Return the name of the NA class. + * + * \param na_class [IN] pointer to NA class + * + * \return Pointer to NA class name or NULL in case of failure + */ +static NA_INLINE const char *NA_Get_class_name(const na_class_t *na_class) NA_WARN_UNUSED_RESULT; + +/** + * Return the protocol of the NA class. + * + * \param na_class [IN] pointer to NA class + * + * \return Pointer to NA class protocol or NULL in case of failure + */ +static NA_INLINE const char *NA_Get_class_protocol(const na_class_t *na_class) NA_WARN_UNUSED_RESULT; + +/** + * Test whether class is listening or not. + * + * \param na_class [IN] pointer to NA class + * + * \return NA_TRUE if listening or NA_FALSE if not + */ +static NA_INLINE na_bool_t NA_Is_listening(const na_class_t *na_class) NA_WARN_UNUSED_RESULT; + +/** + * Create a new context. + * + * \param na_class [IN/OUT] pointer to NA class + * + * \return Pointer to NA context or NULL in case of failure + */ +NA_PUBLIC na_context_t *NA_Context_create(na_class_t *na_class) NA_WARN_UNUSED_RESULT; + +/** + * Create a new context with a specific ID. + * + * \param na_class [IN/OUT] pointer to NA class + * \param id [IN] context ID + * + * \return Pointer to NA context or NULL in case of failure + */ +NA_PUBLIC na_context_t *NA_Context_create_id(na_class_t *na_class, na_uint8_t id) NA_WARN_UNUSED_RESULT; + +/** + * Destroy a context created by using NA_Context_create(). + * + * \param na_class [IN/OUT] pointer to NA class + * \param context [IN/OUT] pointer to context of execution + * + * \return NA_SUCCESS or corresponding NA error code + */ +NA_PUBLIC na_return_t NA_Context_destroy(na_class_t *na_class, na_context_t *context); + +/** + * Allocate an operation ID for the higher level layer to save and + * pass back to the NA layer rather than have the NA layer allocate operation + * IDs all the time. + * Allocating an operation ID gives ownership of that ID to the higher level + * layer, hence it must be explicitly released with NA_Op_destroy() when it + * is no longer needed. + * + * \param na_class [IN/OUT] pointer to NA class + * + * \return valid pointer to operation ID or NULL + */ +NA_PUBLIC na_op_id_t *NA_Op_create(na_class_t *na_class); + +/** + * Destroy operation ID created with NA_Op_create(). + * Reference counting prevents involuntary free. + * + * \param na_class [IN/OUT] pointer to NA class + * \param op_id [IN] pointer to operation ID + * + * \return NA_SUCCESS or corresponding NA error code + */ +NA_PUBLIC na_return_t NA_Op_destroy(na_class_t *na_class, na_op_id_t *op_id); + +/** + * Lookup an addr from a peer address/name. Addresses need to be + * freed by calling NA_Addr_free(). + * + * \param na_class [IN/OUT] pointer to NA class + * \param name [IN] lookup name + * \param addr [OUT] pointer to abstract address + * + * \return NA_SUCCESS or corresponding NA error code + */ +NA_PUBLIC na_return_t NA_Addr_lookup(na_class_t *na_class, const char *name, na_addr_t *addr); + +/** + * Free the addr from the list of peers. + * + * \param na_class [IN/OUT] pointer to NA class + * \param addr [IN] abstract address + * + * \return NA_SUCCESS or corresponding NA error code + */ +NA_PUBLIC na_return_t NA_Addr_free(na_class_t *na_class, na_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 na_class [IN/OUT] pointer to NA class + * \param addr [IN] abstract address + * + * \return NA_SUCCESS or corresponding NA error code + */ +NA_PUBLIC na_return_t NA_Addr_set_remove(na_class_t *na_class, na_addr_t addr); + +/** + * Access self address. + * + * \param na_class [IN/OUT] pointer to NA class + * \param addr [OUT] pointer to abstract address + * + * \return NA_SUCCESS or corresponding NA error code + */ +NA_PUBLIC na_return_t NA_Addr_self(na_class_t *na_class, na_addr_t *addr); + +/** + * Duplicate an existing NA 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 NA_Addr_free(). + * + * \param na_class [IN/OUT] pointer to NA class + * \param addr [IN] abstract address + * \param new_addr [OUT] pointer to abstract address + * + * \return NA_SUCCESS or corresponding NA error code + */ +NA_PUBLIC na_return_t NA_Addr_dup(na_class_t *na_class, na_addr_t addr, na_addr_t *new_addr); + +/** + * Compare two addresses. + * + * \param na_class [IN/OUT] pointer to NA class + * \param addr1 [IN] abstract address + * \param addr2 [IN] abstract address + * + * \return NA_TRUE if addresses are determined to be equal, NA_FALSE otherwise + */ +NA_PUBLIC na_bool_t NA_Addr_cmp(na_class_t *na_class, na_addr_t addr1, na_addr_t addr2); + +/** + * Test whether address is self or not. + * + * \param na_class [IN/OUT] pointer to NA class + * \param addr [IN] abstract address + * + * \return NA_TRUE if self or NA_FALSE if not + */ +static NA_INLINE na_bool_t NA_Addr_is_self(na_class_t *na_class, na_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, NA_OVERFLOW is returned and the buf_size + * output is set to the minimum size required. + * + * \param na_class [IN/OUT] pointer to NA class + * \param buf [IN/OUT] pointer to destination buffer + * \param buf_size [IN/OUT] pointer to buffer size + * \param addr [IN] abstract address + * + * \return NA_SUCCESS or corresponding NA error code + */ +NA_PUBLIC na_return_t NA_Addr_to_string(na_class_t *na_class, char *buf, na_size_t *buf_size, na_addr_t addr); + +/** + * Get size required to serialize address. + * + * \param na_class [IN/OUT] pointer to NA class + * \param addr [IN] abstract address + * + * \return Non-negative value + */ +static NA_INLINE na_size_t NA_Addr_get_serialize_size(na_class_t *na_class, + na_addr_t addr) NA_WARN_UNUSED_RESULT; + +/** + * Serialize address into a buffer. + * + * \param na_class [IN/OUT] pointer to NA class + * \param buf [IN/OUT] pointer to buffer used for serialization + * \param buf_size [IN] buffer size + * \param addr [IN] abstract address + * + * \return NA_SUCCESS or corresponding NA error code + */ +NA_PUBLIC na_return_t NA_Addr_serialize(na_class_t *na_class, void *buf, na_size_t buf_size, na_addr_t addr); + +/** + * Deserialize address from a buffer. The returned address must be freed with + * NA_Addr_free(). + * + * \param na_class [IN/OUT] pointer to NA class + * \param addr [OUT] pointer to abstract address + * \param buf [IN] pointer to buffer used for deserialization + * \param buf_size [IN] buffer size + * + * \return NA_SUCCESS or corresponding NA error code + */ +NA_PUBLIC na_return_t NA_Addr_deserialize(na_class_t *na_class, na_addr_t *addr, const void *buf, + na_size_t buf_size); + +/** + * Get the maximum size of messages supported by unexpected send/recv. + * Small message size. + * + * \param na_class [IN] pointer to NA class + * + * \return Non-negative value + */ +static NA_INLINE na_size_t NA_Msg_get_max_unexpected_size(const na_class_t *na_class) NA_WARN_UNUSED_RESULT; + +/** + * Get the maximum size of messages supported by expected send/recv. + * Small message size that may differ from the unexpected message size. + * + * \param na_class [IN] pointer to NA class + * + * \return Non-negative value + */ +static NA_INLINE na_size_t NA_Msg_get_max_expected_size(const na_class_t *na_class) NA_WARN_UNUSED_RESULT; + +/** + * Get the header size for unexpected messages. Plugins may use that header + * to encode specific information (such as source addr, etc). + * + * \param na_class [IN] pointer to NA class + * + * \return Non-negative value + */ +static NA_INLINE na_size_t NA_Msg_get_unexpected_header_size(const na_class_t *na_class) + NA_WARN_UNUSED_RESULT; + +/** + * Get the header size for expected messages. Plugins may use that header + * to encode specific information. + * + * \param na_class [IN] pointer to NA class + * + * \return Non-negative value + */ +static NA_INLINE na_size_t NA_Msg_get_expected_header_size(const na_class_t *na_class) NA_WARN_UNUSED_RESULT; + +/** + * Get the maximum tag value that can be used by send/recv (both expected and + * unexpected). + * + * \param na_class [IN] pointer to NA class + * + * \return Non-negative value + */ +static NA_INLINE na_tag_t NA_Msg_get_max_tag(const na_class_t *na_class) NA_WARN_UNUSED_RESULT; + +/** + * Allocate buf_size bytes and return a pointer to the allocated memory. + * If size is 0, NA_Msg_buf_alloc() returns NULL. The plugin_data output + * parameter can be used by the underlying plugin implementation to store + * internal memory information. + * + * \param na_class [IN/OUT] pointer to NA class + * \param buf_size [IN] buffer size + * \param plugin_data [OUT] pointer to internal plugin data + * + * \return Pointer to allocated memory or NULL in case of failure + */ +NA_PUBLIC void *NA_Msg_buf_alloc(na_class_t *na_class, na_size_t buf_size, + void **plugin_data) NA_WARN_UNUSED_RESULT; + +/** + * The NA_Msg_buf_free() function releases the memory space pointed to by buf, + * which must have been returned by a previous call to NA_Msg_buf_alloc(). + * If buf is NULL, no operation is performed. + * + * \param na_class [IN/OUT] pointer to NA class + * \param buf [IN] pointer to buffer + * \param plugin_data [IN] pointer to internal plugin data + * + * \return NA_SUCCESS or corresponding NA error code + */ +NA_PUBLIC na_return_t NA_Msg_buf_free(na_class_t *na_class, void *buf, void *plugin_data); + +/** + * Initialize a buffer so that it can be safely passed to the + * NA_Msg_send_unexpected() call. In the case the underlying plugin adds its + * own header to that buffer, the header will be written at this time and the + * usable buffer payload will be buf + NA_Msg_get_unexpected_header_size(). + * + * \param na_class [IN/OUT] pointer to NA class + * \param buf [IN] pointer to buffer + * \param buf_size [IN] buffer size + * + * \return NA_SUCCESS or corresponding NA error code + */ +NA_PUBLIC na_return_t NA_Msg_init_unexpected(na_class_t *na_class, void *buf, na_size_t buf_size); + +/** + * Send an unexpected message to dest_addr. Unexpected sends do not require a + * matching receive to complete. After completion, the user callback is + * placed into the context completion queue and can be triggered using + * NA_Trigger(). + * The plugin_data parameter returned from the NA_Msg_buf_alloc() call must + * be passed along with the buffer, it allows plugins to store and retrieve + * additional buffer information such as memory descriptors. + * \remark Note also that unexpected messages do not require an unexpected + * receive to be posted at the destination before sending the message and the + * destination is allowed to drop the message without notification. However, + * in general, NA plugins are encouraged to remain reliable to avoid unnecessary + * timeouts and cancelations. + * + * Users must manually create an operation ID through NA_Op_create() and pass + * it through op_id for future use and prevent multiple ID creation. + * + * \param na_class [IN/OUT] pointer to NA class + * \param context [IN/OUT] pointer to context of execution + * \param callback [IN] pointer to function callback + * \param arg [IN] pointer to data passed to callback + * \param buf [IN] pointer to send buffer + * \param buf_size [IN] buffer size + * \param plugin_data [IN] pointer to internal plugin data + * \param dest_addr [IN] abstract address of destination + * \param dest_id [IN] destination context ID + * \param tag [IN] tag attached to message + * \param op_id [IN/OUT] pointer to operation ID + * + * \return NA_SUCCESS or corresponding NA error code + */ +static NA_INLINE na_return_t NA_Msg_send_unexpected(na_class_t *na_class, na_context_t *context, + na_cb_t callback, void *arg, const void *buf, + na_size_t buf_size, void *plugin_data, + na_addr_t dest_addr, na_uint8_t dest_id, na_tag_t tag, + na_op_id_t *op_id); + +/** + * Receive an unexpected message. Unexpected receives may wait on any tag and + * any source depending on the implementation. After completion, the user + * callback parameter is placed into the context completion queue and can be + * triggered using NA_Trigger(). + * The plugin_data parameter returned from the NA_Msg_buf_alloc() call must + * be passed along with the buffer, it allows plugins to store and retrieve + * additional buffer information such as memory descriptors. + * + * Users must manually create an operation ID through NA_Op_create() and pass + * it through op_id for future use and prevent multiple ID creation. + * + * \param na_class [IN/OUT] pointer to NA class + * \param context [IN/OUT] pointer to context of execution + * \param callback [IN] pointer to function callback + * \param arg [IN] pointer to data passed to callback + * \param buf [IN] pointer to send buffer + * \param buf_size [IN] buffer size + * \param plugin_data [IN] pointer to internal plugin data + * \param op_id [IN/OUT] pointer to operation ID + * + * \return NA_SUCCESS or corresponding NA error code + */ +static NA_INLINE na_return_t NA_Msg_recv_unexpected(na_class_t *na_class, na_context_t *context, + na_cb_t callback, void *arg, void *buf, + na_size_t buf_size, void *plugin_data, na_op_id_t *op_id); + +/** + * Initialize a buffer so that it can be safely passed to the + * NA_Msg_send_expected() call. In the case the underlying plugin adds its + * own header to that buffer, the header will be written at this time and the + * usable buffer payload will be buf + NA_Msg_get_expected_header_size(). + * + * \param na_class [IN/OUT] pointer to NA class + * \param buf [IN] pointer to buffer + * \param buf_size [IN] buffer size + * + * \return NA_SUCCESS or corresponding NA error code + */ +NA_PUBLIC na_return_t NA_Msg_init_expected(na_class_t *na_class, void *buf, na_size_t buf_size); + +/** + * Send an expected message to dest_addr. After completion, the user callback is + * placed into the context completion queue and can be triggered using + * NA_Trigger(). + * The plugin_data parameter returned from the NA_Msg_buf_alloc() call must + * be passed along with the buffer, it allows plugins to store and retrieve + * additional buffer information such as memory descriptors. + * \remark Note that expected messages require an expected receive to be posted + * at the destination before sending the message, otherwise the destination is + * allowed to drop the message without notification. + * + * Users must manually create an operation ID through NA_Op_create() and pass + * it through op_id for future use and prevent multiple ID creation. + * + * \param na_class [IN/OUT] pointer to NA class + * \param context [IN/OUT] pointer to context of execution + * \param callback [IN] pointer to function callback + * \param arg [IN] pointer to data passed to callback + * \param buf [IN] pointer to send buffer + * \param buf_size [IN] buffer size + * \param plugin_data [IN] pointer to internal plugin data + * \param dest_addr [IN] abstract address of destination + * \param dest_id [IN] destination context ID + * \param tag [IN] tag attached to message + * \param op_id [IN/OUT] pointer to operation ID + * + * \return NA_SUCCESS or corresponding NA error code + */ +static NA_INLINE na_return_t NA_Msg_send_expected(na_class_t *na_class, na_context_t *context, + na_cb_t callback, void *arg, const void *buf, + na_size_t buf_size, void *plugin_data, na_addr_t dest_addr, + na_uint8_t dest_id, na_tag_t tag, na_op_id_t *op_id); + +/** + * Receive an expected message from source_addr. After completion, the user + * callback is placed into the context completion queue and can be triggered + * using NA_Trigger(). + * The plugin_data parameter returned from the NA_Msg_buf_alloc() call must + * be passed along with the buffer, it allows plugins to store and retrieve + * additional buffer information such as memory descriptors. + * + * Users must manually create an operation ID through NA_Op_create() and pass + * it through op_id for future use and prevent multiple ID creation. + * + * \param na_class [IN/OUT] pointer to NA class + * \param context [IN/OUT] pointer to context of execution + * \param callback [IN] pointer to function callback + * \param arg [IN] pointer to data passed to callback + * \param buf [IN] pointer to receive buffer + * \param buf_size [IN] buffer size + * \param plugin_data [IN] pointer to internal plugin data + * \param source_addr [IN] abstract address of source + * \param source_id [IN] source context ID + * \param tag [IN] matching tag used to receive message + * \param op_id [IN/OUT] pointer to operation ID + * + * \return NA_SUCCESS or corresponding NA error code + */ +static NA_INLINE na_return_t NA_Msg_recv_expected(na_class_t *na_class, na_context_t *context, + na_cb_t callback, void *arg, void *buf, na_size_t buf_size, + void *plugin_data, na_addr_t source_addr, + na_uint8_t source_id, na_tag_t tag, na_op_id_t *op_id); + +/** + * Create memory handle for RMA operations. + * For non-contiguous memory, use NA_Mem_handle_create_segments() instead. + * + * \remark Note to plugin developers: NA_Mem_handle_create() may be called + * multiple times on the same memory region. + * + * \param na_class [IN/OUT] pointer to NA class + * \param buf [IN] pointer to buffer that needs to be registered + * \param buf_size [IN] buffer size + * \param flags [IN] permission flag: + * - NA_MEM_READWRITE + * - NA_MEM_READ_ONLY + * \param mem_handle [OUT] pointer to returned abstract memory handle + * + * \return NA_SUCCESS or corresponding NA error code + */ +NA_PUBLIC na_return_t NA_Mem_handle_create(na_class_t *na_class, void *buf, na_size_t buf_size, + unsigned long flags, na_mem_handle_t *mem_handle); + +/** + * Create memory handle for RMA operations. + * Create_segments can be used to register scatter-gather lists and get a single + * memory handle. + * \remark Implemented only if the network transport or hardware supports it. + * + * \param na_class [IN/OUT] pointer to NA class + * \param segments [IN] pointer to array of segments composed of: + * - address of the segment that needs to be + * registered + * - size of the segment in bytes + * \param segment_count [IN] segment count + * \param flags [IN] permission flag: + * - NA_MEM_READWRITE + * - NA_MEM_READ_ONLY + * \param mem_handle [OUT] pointer to returned abstract memory handle + * + * \return NA_SUCCESS or corresponding NA error code + */ +NA_PUBLIC na_return_t NA_Mem_handle_create_segments(na_class_t *na_class, struct na_segment *segments, + na_size_t segment_count, unsigned long flags, + na_mem_handle_t *mem_handle); + +/** + * Free memory handle. + * + * \param na_class [IN/OUT] pointer to NA class + * \param mem_handle [IN] abstract memory handle + * + * \return NA_SUCCESS or corresponding NA error code + */ +NA_PUBLIC na_return_t NA_Mem_handle_free(na_class_t *na_class, na_mem_handle_t mem_handle); + +/** + * Get the maximum segment count that can be passed to + * NA_Mem_handle_create_segments(). + * + * \param na_class [IN] pointer to NA class + * + * \return Non-negative value + */ +static NA_INLINE na_size_t NA_Mem_handle_get_max_segments(const na_class_t *na_class) NA_WARN_UNUSED_RESULT; + +/** + * Register memory for RMA operations. + * Memory pieces must be registered before one-sided transfers can be + * initiated. + * + * \param na_class [IN/OUT] pointer to NA class + * \param mem_handle [IN] pointer to abstract memory handle + * + * \return NA_SUCCESS or corresponding NA error code + */ +NA_PUBLIC na_return_t NA_Mem_register(na_class_t *na_class, na_mem_handle_t mem_handle); + +/** + * Unregister memory. + * + * \param na_class [IN/OUT] pointer to NA class + * \param mem_handle [IN] abstract memory handle + * + * \return NA_SUCCESS or corresponding NA error code + */ +NA_PUBLIC na_return_t NA_Mem_deregister(na_class_t *na_class, na_mem_handle_t mem_handle); + +/** + * Get size required to serialize handle. + * + * \param na_class [IN/OUT] pointer to NA class + * \param mem_handle [IN] abstract memory handle + * + * \return Non-negative value + */ +static NA_INLINE na_size_t NA_Mem_handle_get_serialize_size(na_class_t * na_class, + na_mem_handle_t mem_handle) NA_WARN_UNUSED_RESULT; + +/** + * Serialize memory handle into a buffer. + * One-sided transfers require prior exchange of memory handles between + * peers, serialization callbacks can be used to "pack" a memory handle and + * send it across the network. + * \remark Memory handles can be variable size, therefore the space required + * to serialize a handle into a buffer can be obtained using + * NA_Mem_handle_get_serialize_size(). + * + * \param na_class [IN/OUT] pointer to NA class + * \param buf [IN/OUT] pointer to buffer used for serialization + * \param buf_size [IN] buffer size + * \param mem_handle [IN] abstract memory handle + * + * \return NA_SUCCESS or corresponding NA error code + */ +NA_PUBLIC na_return_t NA_Mem_handle_serialize(na_class_t *na_class, void *buf, na_size_t buf_size, + na_mem_handle_t mem_handle); + +/** + * Deserialize memory handle from buffer. + * + * \param na_class [IN/OUT] pointer to NA class + * \param mem_handle [OUT] pointer to abstract memory handle + * \param buf [IN] pointer to buffer used for deserialization + * \param buf_size [IN] buffer size + * + * \return NA_SUCCESS or corresponding NA error code + */ +NA_PUBLIC na_return_t NA_Mem_handle_deserialize(na_class_t *na_class, na_mem_handle_t *mem_handle, + const void *buf, na_size_t buf_size); + +/** + * Put data to remote address. + * Initiate a put to the registered memory regions with the given offset/size. + * After completion, the user callback is placed into a completion queue and + * can be triggered using NA_Trigger(). + * \remark Memory must be registered and handles exchanged between peers. + * + * Users must manually create an operation ID through NA_Op_create() and pass + * it through op_id for future use and prevent multiple ID creation. + * + * \param na_class [IN/OUT] pointer to NA class + * \param context [IN/OUT] pointer to context of execution + * \param callback [IN] pointer to function callback + * \param arg [IN] pointer to data passed to callback + * \param local_mem_handle [IN] abstract local memory handle + * \param local_offset [IN] local offset + * \param remote_mem_handle [IN] abstract remote memory handle + * \param remote_offset [IN] remote offset + * \param data_size [IN] size of data that needs to be transferred + * \param remote_addr [IN] abstract address of remote destination + * \param remote_id [IN] target ID of remote destination + * \param op_id [IN/OUT] pointer to operation ID + * + * \return NA_SUCCESS or corresponding NA error code + */ +static NA_INLINE na_return_t NA_Put(na_class_t *na_class, na_context_t *context, na_cb_t callback, void *arg, + na_mem_handle_t local_mem_handle, na_offset_t local_offset, + na_mem_handle_t remote_mem_handle, na_offset_t remote_offset, + na_size_t data_size, na_addr_t remote_addr, na_uint8_t remote_id, + na_op_id_t *op_id); + +/** + * Get data from remote address. + * Initiate a get to the registered memory regions with the given offset/size. + * After completion, the user callback is placed into a completion queue and + * can be triggered using NA_Trigger(). + * + * Users must manually create an operation ID through NA_Op_create() and pass + * it through op_id for future use and prevent multiple ID creation. + * + * \param na_class [IN/OUT] pointer to NA class + * \param context [IN/OUT] pointer to context of execution + * \param callback [IN] pointer to function callback + * \param arg [IN] pointer to data passed to callback + * \param local_mem_handle [IN] abstract local memory handle + * \param local_offset [IN] local offset + * \param remote_mem_handle [IN] abstract remote memory handle + * \param remote_offset [IN] remote offset + * \param data_size [IN] size of data that needs to be transferred + * \param remote_addr [IN] abstract address of remote source + * \param remote_id [IN] target ID of remote source + * \param op_id [IN/OUT] pointer to operation ID + * + * \return NA_SUCCESS or corresponding NA error code + */ +static NA_INLINE na_return_t NA_Get(na_class_t *na_class, na_context_t *context, na_cb_t callback, void *arg, + na_mem_handle_t local_mem_handle, na_offset_t local_offset, + na_mem_handle_t remote_mem_handle, na_offset_t remote_offset, + na_size_t data_size, na_addr_t remote_addr, na_uint8_t remote_id, + na_op_id_t *op_id); + +/** + * Retrieve file descriptor from NA plugin when supported. The descriptor + * can be used by upper layers for manual polling through the usual + * OS select/poll/epoll calls. + * + * \param na_class [IN/OUT] pointer to NA class + * \param context [IN/OUT] pointer to context of execution + * + * \return Non-negative integer if supported, 0 if not implemented and negative + * in case of error. + */ +static NA_INLINE int NA_Poll_get_fd(na_class_t *na_class, na_context_t *context) NA_WARN_UNUSED_RESULT; + +/** + * Used to signal when it is safe to block on the class/context poll descriptor + * or if there is already work that can be progressed. + * + * \param na_class [IN/OUT] pointer to NA class + * \param context [IN/OUT] pointer to context of execution + * + * \return NA_TRUE if it is safe to block or NA_FALSE otherwise + */ +NA_PUBLIC na_bool_t NA_Poll_try_wait(na_class_t *na_class, na_context_t *context); + +/** + * Try to progress communication 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 na_class [IN/OUT] pointer to NA class + * \param context [IN/OUT] pointer to context of execution + * \param timeout [IN] timeout (in milliseconds) + * + * \return NA_SUCCESS if any completion has occurred / NA error code otherwise + */ +NA_PUBLIC na_return_t NA_Progress(na_class_t *na_class, na_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/OUT] pointer to context of execution + * \param timeout [IN] timeout (in milliseconds) + * \param max_count [IN] maximum number of callbacks triggered + * \param callback_ret [IN/OUT] array of callback return values + * \param actual_count [OUT] actual number of callbacks triggered + * + * \return NA_SUCCESS or corresponding NA error code + */ +NA_PUBLIC na_return_t NA_Trigger(na_context_t *context, unsigned int timeout, unsigned int max_count, + int callback_ret[], unsigned int *actual_count); + +/** + * Cancel an ongoing operation. + * + * \param na_class [IN/OUT] pointer to NA class + * \param context [IN/OUT] pointer to context of execution + * \param op_id [IN] pointer to operation ID + * + * \return NA_SUCCESS or corresponding NA error code + */ +NA_PUBLIC na_return_t NA_Cancel(na_class_t *na_class, na_context_t *context, na_op_id_t *op_id); + +/** + * Convert error return code to string (null terminated). + * + * \param errnum [IN] error return code + * + * \return String + */ +NA_PUBLIC const char *NA_Error_to_string(na_return_t errnum) NA_WARN_UNUSED_RESULT; + +/************************************/ +/* Local Type and Struct Definition */ +/************************************/ + +/* NA info definition */ +struct na_info { + char *class_name; /* Class name (e.g., bmi) */ + char *protocol_name; /* Protocol (e.g., tcp, ib) */ + char *host_name; /* Host (may be NULL in anonymous mode) */ + /* Additional init info (NULL if no info) */ + const struct na_init_info *na_init_info; +}; + +/* NA class definition */ +struct na_class { + const struct na_class_ops *ops; /* Class operations */ + void * plugin_class; /* Plugin private class */ + char * protocol_name; /* Name of protocol */ + na_uint32_t progress_mode; /* NA progress mode */ + na_bool_t listen; /* Listen for connections */ +}; + +/* NA context definition */ +struct na_context { + void *plugin_context; /* Plugin private context */ +}; + +/* NA plugin callbacks */ +struct na_class_ops { + const char *class_name; + na_bool_t (*check_protocol)(const char *protocol_name); + na_return_t (*initialize)(na_class_t *na_class, const struct na_info *na_info, na_bool_t listen); + na_return_t (*finalize)(na_class_t *na_class); + void (*cleanup)(void); + na_return_t (*context_create)(na_class_t *na_class, void **plugin_context, na_uint8_t id); + na_return_t (*context_destroy)(na_class_t *na_class, void *plugin_context); + na_op_id_t *(*op_create)(na_class_t *na_class); + na_return_t (*op_destroy)(na_class_t *na_class, na_op_id_t *op_id); + na_return_t (*addr_lookup)(na_class_t *na_class, const char *name, na_addr_t *addr); + na_return_t (*addr_free)(na_class_t *na_class, na_addr_t addr); + na_return_t (*addr_set_remove)(na_class_t *na_class, na_addr_t addr); + na_return_t (*addr_self)(na_class_t *na_class, na_addr_t *addr); + na_return_t (*addr_dup)(na_class_t *na_class, na_addr_t addr, na_addr_t *new_addr); + na_bool_t (*addr_cmp)(na_class_t *na_class, na_addr_t addr1, na_addr_t addr2); + na_bool_t (*addr_is_self)(na_class_t *na_class, na_addr_t addr); + na_return_t (*addr_to_string)(na_class_t *na_class, char *buf, na_size_t *buf_size, na_addr_t addr); + na_size_t (*addr_get_serialize_size)(na_class_t *na_class, na_addr_t addr); + na_return_t (*addr_serialize)(na_class_t *na_class, void *buf, na_size_t buf_size, na_addr_t addr); + na_return_t (*addr_deserialize)(na_class_t *na_class, na_addr_t *addr, const void *buf, + na_size_t buf_size); + na_size_t (*msg_get_max_unexpected_size)(const na_class_t *na_class); + na_size_t (*msg_get_max_expected_size)(const na_class_t *na_class); + na_size_t (*msg_get_unexpected_header_size)(const na_class_t *na_class); + na_size_t (*msg_get_expected_header_size)(const na_class_t *na_class); + na_tag_t (*msg_get_max_tag)(const na_class_t *na_class); + void *(*msg_buf_alloc)(na_class_t *na_class, na_size_t buf_size, void **plugin_data); + na_return_t (*msg_buf_free)(na_class_t *na_class, void *buf, void *plugin_data); + na_return_t (*msg_init_unexpected)(na_class_t *na_class, void *buf, na_size_t buf_size); + na_return_t (*msg_send_unexpected)(na_class_t *na_class, na_context_t *context, na_cb_t callback, + void *arg, const void *buf, na_size_t buf_size, void *plugin_data, + na_addr_t dest_addr, na_uint8_t dest_id, na_tag_t tag, + na_op_id_t *op_id); + na_return_t (*msg_recv_unexpected)(na_class_t *na_class, na_context_t *context, na_cb_t callback, + void *arg, void *buf, na_size_t buf_size, void *plugin_data, + na_op_id_t *op_id); + na_return_t (*msg_init_expected)(na_class_t *na_class, void *buf, na_size_t buf_size); + na_return_t (*msg_send_expected)(na_class_t *na_class, na_context_t *context, na_cb_t callback, void *arg, + const void *buf, na_size_t buf_size, void *plugin_data, + na_addr_t dest_addr, na_uint8_t dest_id, na_tag_t tag, + na_op_id_t *op_id); + na_return_t (*msg_recv_expected)(na_class_t *na_class, na_context_t *context, na_cb_t callback, void *arg, + void *buf, na_size_t buf_size, void *plugin_data, na_addr_t source_addr, + na_uint8_t source_id, na_tag_t tag, na_op_id_t *op_id); + na_return_t (*mem_handle_create)(na_class_t *na_class, void *buf, na_size_t buf_size, unsigned long flags, + na_mem_handle_t *mem_handle); + na_return_t (*mem_handle_create_segments)(na_class_t *na_class, struct na_segment *segments, + na_size_t segment_count, unsigned long flags, + na_mem_handle_t *mem_handle); + na_return_t (*mem_handle_free)(na_class_t *na_class, na_mem_handle_t mem_handle); + na_size_t (*mem_handle_get_max_segments)(const na_class_t *na_class); + na_return_t (*mem_register)(na_class_t *na_class, na_mem_handle_t mem_handle); + na_return_t (*mem_deregister)(na_class_t *na_class, na_mem_handle_t mem_handle); + na_size_t (*mem_handle_get_serialize_size)(na_class_t *na_class, na_mem_handle_t mem_handle); + na_return_t (*mem_handle_serialize)(na_class_t *na_class, void *buf, na_size_t buf_size, + na_mem_handle_t mem_handle); + na_return_t (*mem_handle_deserialize)(na_class_t *na_class, na_mem_handle_t *mem_handle, const void *buf, + na_size_t buf_size); + na_return_t (*put)(na_class_t *na_class, na_context_t *context, na_cb_t callback, void *arg, + na_mem_handle_t local_mem_handle, na_offset_t local_offset, + na_mem_handle_t remote_mem_handle, na_offset_t remote_offset, na_size_t length, + na_addr_t remote_addr, na_uint8_t remote_id, na_op_id_t *op_id); + na_return_t (*get)(na_class_t *na_class, na_context_t *context, na_cb_t callback, void *arg, + na_mem_handle_t local_mem_handle, na_offset_t local_offset, + na_mem_handle_t remote_mem_handle, na_offset_t remote_offset, na_size_t length, + na_addr_t remote_addr, na_uint8_t remote_id, na_op_id_t *op_id); + int (*na_poll_get_fd)(na_class_t *na_class, na_context_t *context); + na_bool_t (*na_poll_try_wait)(na_class_t *na_class, na_context_t *context); + na_return_t (*progress)(na_class_t *na_class, na_context_t *context, unsigned int timeout); + na_return_t (*cancel)(na_class_t *na_class, na_context_t *context, na_op_id_t *op_id); +}; + +/*---------------------------------------------------------------------------*/ +static NA_INLINE const char * +NA_Get_class_name(const na_class_t *na_class) +{ + return na_class->ops->class_name; +} + +/*---------------------------------------------------------------------------*/ +static NA_INLINE const char * +NA_Get_class_protocol(const na_class_t *na_class) +{ + return na_class->protocol_name; +} + +/*---------------------------------------------------------------------------*/ +static NA_INLINE na_bool_t +NA_Is_listening(const na_class_t *na_class) +{ + return na_class->listen; +} + +/*---------------------------------------------------------------------------*/ +static NA_INLINE na_bool_t +NA_Addr_is_self(na_class_t *na_class, na_addr_t addr) +{ + return na_class->ops->addr_is_self(na_class, addr); +} + +/*---------------------------------------------------------------------------*/ +static NA_INLINE na_size_t +NA_Addr_get_serialize_size(na_class_t *na_class, na_addr_t addr) +{ + return (na_class->ops->addr_get_serialize_size) ? na_class->ops->addr_get_serialize_size(na_class, addr) + : 0; +} + +/*---------------------------------------------------------------------------*/ +static NA_INLINE na_size_t +NA_Msg_get_max_unexpected_size(const na_class_t *na_class) +{ + return na_class->ops->msg_get_max_unexpected_size(na_class); +} + +/*---------------------------------------------------------------------------*/ +static NA_INLINE na_size_t +NA_Msg_get_max_expected_size(const na_class_t *na_class) +{ + return na_class->ops->msg_get_max_expected_size(na_class); +} + +/*---------------------------------------------------------------------------*/ +static NA_INLINE na_size_t +NA_Msg_get_unexpected_header_size(const na_class_t *na_class) +{ + return (na_class->ops->msg_get_unexpected_header_size) + ? na_class->ops->msg_get_unexpected_header_size(na_class) + : 0; +} + +/*---------------------------------------------------------------------------*/ +static NA_INLINE na_size_t +NA_Msg_get_expected_header_size(const na_class_t *na_class) +{ + return (na_class->ops->msg_get_expected_header_size) + ? na_class->ops->msg_get_expected_header_size(na_class) + : 0; +} + +/*---------------------------------------------------------------------------*/ +static NA_INLINE na_tag_t +NA_Msg_get_max_tag(const na_class_t *na_class) +{ + return na_class->ops->msg_get_max_tag(na_class); +} + +/*---------------------------------------------------------------------------*/ +static NA_INLINE na_return_t +NA_Msg_send_unexpected(na_class_t *na_class, na_context_t *context, na_cb_t callback, void *arg, + const void *buf, na_size_t buf_size, void *plugin_data, na_addr_t dest_addr, + na_uint8_t dest_id, na_tag_t tag, na_op_id_t *op_id) +{ + return na_class->ops->msg_send_unexpected(na_class, context, callback, arg, buf, buf_size, plugin_data, + dest_addr, dest_id, tag, op_id); +} + +/*---------------------------------------------------------------------------*/ +static NA_INLINE na_return_t +NA_Msg_recv_unexpected(na_class_t *na_class, na_context_t *context, na_cb_t callback, void *arg, void *buf, + na_size_t buf_size, void *plugin_data, na_op_id_t *op_id) +{ + return na_class->ops->msg_recv_unexpected(na_class, context, callback, arg, buf, buf_size, plugin_data, + op_id); +} + +/*---------------------------------------------------------------------------*/ +static NA_INLINE na_return_t +NA_Msg_send_expected(na_class_t *na_class, na_context_t *context, na_cb_t callback, void *arg, + const void *buf, na_size_t buf_size, void *plugin_data, na_addr_t dest_addr, + na_uint8_t dest_id, na_tag_t tag, na_op_id_t *op_id) +{ + return na_class->ops->msg_send_expected(na_class, context, callback, arg, buf, buf_size, plugin_data, + dest_addr, dest_id, tag, op_id); +} + +/*---------------------------------------------------------------------------*/ +static NA_INLINE na_return_t +NA_Msg_recv_expected(na_class_t *na_class, na_context_t *context, na_cb_t callback, void *arg, void *buf, + na_size_t buf_size, void *plugin_data, na_addr_t source_addr, na_uint8_t source_id, + na_tag_t tag, na_op_id_t *op_id) +{ + return na_class->ops->msg_recv_expected(na_class, context, callback, arg, buf, buf_size, plugin_data, + source_addr, source_id, tag, op_id); +} + +/*---------------------------------------------------------------------------*/ +static NA_INLINE na_size_t +NA_Mem_handle_get_max_segments(const na_class_t *na_class) +{ + return (na_class->ops->mem_handle_get_max_segments) ? na_class->ops->mem_handle_get_max_segments(na_class) + : 1; +} + +/*---------------------------------------------------------------------------*/ +static NA_INLINE na_size_t +NA_Mem_handle_get_serialize_size(na_class_t *na_class, na_mem_handle_t mem_handle) +{ + return na_class->ops->mem_handle_get_serialize_size(na_class, mem_handle); +} + +/*---------------------------------------------------------------------------*/ +static NA_INLINE na_return_t +NA_Put(na_class_t *na_class, na_context_t *context, na_cb_t callback, void *arg, + na_mem_handle_t local_mem_handle, na_offset_t local_offset, na_mem_handle_t remote_mem_handle, + na_offset_t remote_offset, na_size_t data_size, na_addr_t remote_addr, na_uint8_t remote_id, + na_op_id_t *op_id) +{ + return na_class->ops->put(na_class, context, callback, arg, local_mem_handle, local_offset, + remote_mem_handle, remote_offset, data_size, remote_addr, remote_id, op_id); +} + +/*---------------------------------------------------------------------------*/ +static NA_INLINE na_return_t +NA_Get(na_class_t *na_class, na_context_t *context, na_cb_t callback, void *arg, + na_mem_handle_t local_mem_handle, na_offset_t local_offset, na_mem_handle_t remote_mem_handle, + na_offset_t remote_offset, na_size_t data_size, na_addr_t remote_addr, na_uint8_t remote_id, + na_op_id_t *op_id) +{ + return na_class->ops->get(na_class, context, callback, arg, local_mem_handle, local_offset, + remote_mem_handle, remote_offset, data_size, remote_addr, remote_id, op_id); +} + +/*---------------------------------------------------------------------------*/ +static NA_INLINE int +NA_Poll_get_fd(na_class_t *na_class, na_context_t *context) +{ + return (na_class->ops->na_poll_get_fd) ? na_class->ops->na_poll_get_fd(na_class, context) : -1; +} + +#ifdef __cplusplus +} +#endif + +#endif /* NA_H */ |