32 #include <sys/types.h>
50 #define SLEEP_IN_NANOS (10 * 1000)
52 #define SAMPLE_ASSERT(condition, result, state, error...) \
55 DOCA_LOG_ERR(error); \
61 #define CB_ASSERT(condition, result, cb_result, error...) \
64 DOCA_LOG_ERR(error); \
65 *(cb_result) = (result); \
70 #define ASSERT_DOCA_ERR(result, state, error) \
71 SAMPLE_ASSERT((result) == DOCA_SUCCESS, (result), state, (error ": %s"), doca_error_get_descr(result))
73 #define NUM_EC_TASKS (8)
74 #define USER_MAX_PATH_NAME 255
75 #define MAX_PATH_NAME (USER_MAX_PATH_NAME + 1)
76 #define MAX_DATA_SIZE (MAX_PATH_NAME + 100)
77 #define RECOVERED_FILE_NAME "_recovered"
78 #define DATA_INFO_FILE_NAME "data_info"
79 #define DATA_BLOCK_FILE_NAME "data_block_"
80 #define RDNC_BLOCK_FILE_NAME "rdnc_block_"
112 DOCA_LOG_ERR(
"Failed to decrease DOCA buffer reference count: %s",
118 DOCA_LOG_ERR(
"Failed to decrease DOCA buffer reference count: %s",
174 struct doca_ctx *
ctx,
183 switch (next_state) {
193 DOCA_LOG_ERR(
"Erasure Coding context entered into starting state. Unexpected transition");
206 DOCA_LOG_INFO(
"Erasure Coding context entered into stopping state. Any inflight tasks will be flushed");
227 const char *pci_addr,
233 uint64_t *max_block_size)
237 uint32_t max_buf_list_len = 0;
253 if ((uint32_t)(num_src_buf + num_dst_buf) > max_buf_list_len) {
255 DOCA_LOG_ERR(
"Number of doca_buf [%d] exceed the limitation [%u]: %s",
256 num_src_buf + num_dst_buf,
301 ctx_user_data.
ptr = state;
389 "Unable to retrieve data pointer from redundancy data blocks buffer");
392 ret = snprintf(full_path,
398 CB_ASSERT(ret >= 0 && ret < (
int)
sizeof(full_path),
401 "Path exceeded max path len");
406 "Unable to open output file: %s",
440 const char *file_path,
442 const char *output_dir_path,
443 uint32_t data_block_count,
444 uint32_t rdnc_block_count,
452 uint64_t max_block_size;
459 struct timespec ts = {
465 struct doca_task *doca_task;
466 struct doca_ec_task_create *task;
473 block_size = file_size / data_block_count;
474 if (block_size * data_block_count != file_size)
476 if (block_size % 64 != 0)
477 block_size += 64 - (block_size % 64);
478 src_size = (uint64_t)block_size * data_block_count;
479 dst_size = (uint64_t)block_size * rdnc_block_count;
488 for (i = 0; i < data_block_count; i++) {
489 ret = snprintf(full_path,
sizeof(full_path),
"%s/%s%ld", output_dir_path,
DATA_BLOCK_FILE_NAME, i);
493 "Path exceeded max path len");
498 "Unable to open output file: %s",
506 ret = snprintf(full_path,
sizeof(full_path),
"%s/%s", output_dir_path,
DATA_INFO_FILE_NAME);
510 "Path exceeded max path len");
515 "Unable to open output file: %s",
517 ret = fprintf(state->
block_file,
"%ld %.*s", file_size, (
int)strlen(file_path), file_path);
553 block_size <= max_block_size,
556 "Block size (%lu) exceeds the maximum size supported (%lu). Try to increase the number of blocks or use a smaller file as input",
566 .cb_result = &callback_result};
567 user_data.
ptr = &task_data;
604 return callback_result;
658 size_t block_file_size = 0, remaining_file_size;
669 "Unable to retrieve data pointer from redundancy data blocks buffer");
671 for (i = 0; i < task_data->
n_missing; i++) {
672 ret = snprintf(full_path,
678 CB_ASSERT(ret >= 0 && ret < (
int)
sizeof(full_path),
681 "Path exceeded max path len");
686 "Unable to open output file: %s",
694 remaining_file_size = task_data->
file_size;
697 CB_ASSERT(ret >= 0 && ret < (
int)
sizeof(full_path),
700 "Path exceeded max path len");
703 if (remaining_file_size < block_file_size)
704 block_file_size = remaining_file_size;
707 remaining_file_size -= block_file_size;
711 if (remaining_file_size == 0)
742 const char *user_output_file_path,
743 const char *dir_path,
744 uint32_t data_block_count,
745 uint32_t rdnc_block_count,
752 uint64_t max_block_size;
753 size_t block_file_size;
754 uint64_t block_size = 0;
756 uint64_t src_size = -1;
757 uint64_t src_size_cur = 0;
761 size_t n_missing = 0;
766 struct timespec ts = {
772 struct doca_task *doca_task;
773 struct doca_ec_task_recover *task;
781 "Path exceeded max path len");
788 "File data info may be nonfinite");
793 if (user_output_file_path !=
NULL) {
797 "Path exceeded max path len");
798 strcpy(output_file_path, user_output_file_path);
804 "File data info contain file path bigger then max size");
805 ret = snprintf(output_file_path,
806 sizeof(output_file_path),
811 SAMPLE_ASSERT(ret >= 0 && ret < (
int)
sizeof(output_file_path),
814 "Path exceeded max path len");
820 state->
out_file = fopen(output_file_path,
"wr");
824 "Unable to open output file: %s",
827 state->
missing_indices = calloc(data_block_count + rdnc_block_count,
sizeof(uint32_t));
830 for (i = 0; i < data_block_count + rdnc_block_count; i++) {
832 size_t index = i < data_block_count ? i : i - data_block_count;
834 ret = snprintf(full_path,
sizeof(full_path),
"%s/%s%ld", dir_path, file_name, index);
838 "Path exceeded max path len");
841 block_size = block_file_size;
845 "Block size is not 64 byte aligned");
846 src_size = (uint64_t)block_size * data_block_count;
851 "Unable to allocate src_buffer string");
857 "Blocks are not same size");
860 src_size_cur += block_size;
865 if (src_size_cur == src_size)
873 "Nothing to decode, all original data block are in place");
874 dst_size = block_size * n_missing;
891 block_size <= max_block_size,
894 "Block size (%lu) exceeds the maximum size supported (%lu). Try to increase the number of blocks or use a smaller file as input",
933 .cb_result = &callback_result};
934 user_data.
ptr = &task_data;
973 return callback_result;
990 for (i = 0; i < n_missing; i++) {
991 ret = snprintf(full_path,
997 if ((ret >= 0 && ret < (
int)
sizeof(full_path)) && remove(full_path) == 0)
1022 const char *input_path,
1023 const char *output_path,
1026 uint32_t data_block_count,
1027 uint32_t rdnc_block_count,
1028 uint32_t *missing_indices,
1034 struct stat path_stat;
1035 bool input_path_is_file;
1036 const char *dir_path = output_path;
1037 const char *output_file_path =
NULL;
1039 if (stat(input_path, &path_stat) != 0) {
1040 DOCA_LOG_INFO(
"Can't read input file stat: %s", input_path);
1043 input_path_is_file = S_ISREG(path_stat.st_mode);
1044 if (!do_both && !input_path_is_file) {
1045 dir_path = input_path;
1046 output_file_path = output_path;
1049 if (do_both || input_path_is_file)
1064 if (do_both || !input_path_is_file)
doca_error_t allocat_doca_buf_list(struct doca_buf_inventory *buf_inv, struct doca_mmap *mmap, void *buf_addr, size_t buf_len, int num_buf, bool set_data_pos, struct doca_buf **dbuf)
doca_error_t destroy_core_objects(struct program_core_objects *state)
doca_error_t create_core_objects(struct program_core_objects *state, uint32_t max_bufs)
static doca_error_t open_doca_device_with_pci(const char *pcie_value, struct doca_dev **retval)
#define DATA_INFO_FILE_NAME
#define CB_ASSERT(condition, result, cb_result, error...)
static doca_error_t ec_core_init(struct ec_sample_objects *state, const char *pci_addr, tasks_check is_support_func, uint32_t src_size, uint32_t dst_size, int num_src_buf, int num_dst_buf, uint64_t *max_block_size)
DOCA_LOG_REGISTER(EC_RECOVER)
static void ec_cleanup(struct ec_sample_objects *state)
#define DATA_BLOCK_FILE_NAME
doca_error_t ec_recover(const char *pci_addr, const char *input_path, const char *output_path, bool do_both, enum doca_ec_matrix_type matrix_type, uint32_t data_block_count, uint32_t rdnc_block_count, uint32_t *missing_indices, size_t n_missing, int num_src_buf, int num_dst_buf)
#define SAMPLE_ASSERT(condition, result, state, error...)
static void ec_create_completed_callback(struct doca_ec_task_create *create_task, union doca_data task_user_data, union doca_data ctx_user_data)
static void ec_task_error(struct doca_task *task, doca_error_t *task_status, doca_error_t *cb_result)
#define RDNC_BLOCK_FILE_NAME
static void ec_recover_error_callback(struct doca_ec_task_recover *recover_task, union doca_data task_user_data, union doca_data ctx_user_data)
#define ASSERT_DOCA_ERR(result, state, error)
static void ec_create_error_callback(struct doca_ec_task_create *create_task, union doca_data task_user_data, union doca_data ctx_user_data)
#define USER_MAX_PATH_NAME
#define RECOVERED_FILE_NAME
static void ec_state_changed_callback(const union doca_data user_data, struct doca_ctx *ctx, enum doca_ctx_states prev_state, enum doca_ctx_states next_state)
static void ec_recover_completed_callback(struct doca_ec_task_recover *recover_task, union doca_data task_user_data, union doca_data ctx_user_data)
doca_error_t ec_decode(const char *pci_addr, enum doca_ec_matrix_type matrix_type, const char *user_output_file_path, const char *dir_path, uint32_t data_block_count, uint32_t rdnc_block_count, int num_src_buf, int num_dst_buf)
doca_error_t ec_delete_data(const char *output_path, uint32_t *missing_indices, size_t n_missing)
doca_error_t ec_encode(const char *pci_addr, const char *file_path, enum doca_ec_matrix_type matrix_type, const char *output_dir_path, uint32_t data_block_count, uint32_t rdnc_block_count, int num_src_buf, int num_dst_buf)
DOCA_STABLE doca_error_t doca_buf_dec_refcount(struct doca_buf *buf, uint16_t *refcount)
Decrease the object reference count by 1, if 0 reached, return the element back to the inventory.
DOCA_STABLE doca_error_t doca_buf_get_data(const struct doca_buf *buf, void **data)
Get the buffer's data.
DOCA_STABLE doca_error_t doca_ctx_start(struct doca_ctx *ctx)
Finalizes all configurations, and starts the DOCA CTX.
DOCA_STABLE doca_error_t doca_ctx_set_state_changed_cb(struct doca_ctx *ctx, doca_ctx_state_changed_callback_t cb)
Set state changed callback.
DOCA_STABLE doca_error_t doca_ctx_set_user_data(struct doca_ctx *ctx, union doca_data user_data)
set user data to context
DOCA_STABLE doca_error_t doca_ctx_stop(struct doca_ctx *ctx)
Stops the context allowing reconfiguration.
doca_ctx_states
This enum defines the states of a context.
@ DOCA_CTX_STATE_STARTING
@ DOCA_CTX_STATE_STOPPING
DOCA_STABLE struct doca_devinfo * doca_dev_as_devinfo(const struct doca_dev *dev)
Get local device info from device. This should be useful when wanting to query information about devi...
DOCA_EXPERIMENTAL doca_error_t doca_ec_cap_task_create_is_supported(const struct doca_devinfo *devinfo)
DOCA_EXPERIMENTAL doca_error_t doca_ec_task_create_set_conf(struct doca_ec *ec, doca_ec_task_create_completion_cb_t successful_task_completion_cb, doca_ec_task_create_completion_cb_t error_task_completion_cb, uint32_t num_tasks)
This method sets the create tasks configuration.
DOCA_EXPERIMENTAL doca_error_t doca_ec_destroy(struct doca_ec *ec)
Destroy a DOCA EC instance.
doca_ec_matrix_type
Types of coding matrix used for erasure codes.
DOCA_EXPERIMENTAL doca_error_t doca_ec_task_create_allocate_init(struct doca_ec *ec, const struct doca_ec_matrix *coding_matrix, const struct doca_buf *original_data_blocks, struct doca_buf *rdnc_blocks, union doca_data user_data, struct doca_ec_task_create **task)
This method allocates and initializes a create task.
DOCA_EXPERIMENTAL doca_error_t doca_ec_cap_get_max_buf_list_len(const struct doca_devinfo *devinfo, uint32_t *max_buf_list_len)
Get the maximum supported number of elements in DOCA linked-list buffer used for EC tasks.
DOCA_EXPERIMENTAL doca_error_t doca_ec_create(struct doca_dev *dev, struct doca_ec **ec)
Create a DOCA EC instance.
DOCA_EXPERIMENTAL doca_error_t doca_ec_task_recover_allocate_init(struct doca_ec *ec, const struct doca_ec_matrix *recover_matrix, const struct doca_buf *available_blocks, struct doca_buf *recovered_data_blocks, union doca_data user_data, struct doca_ec_task_recover **task)
This method allocates and initializes a recover task.
DOCA_EXPERIMENTAL doca_error_t doca_ec_matrix_destroy(struct doca_ec_matrix *matrix)
Destroy coding matrix.
DOCA_EXPERIMENTAL struct doca_task * doca_ec_task_recover_as_task(struct doca_ec_task_recover *task)
This method converts an EC recover task to a doca_task.
DOCA_EXPERIMENTAL doca_error_t doca_ec_task_recover_set_conf(struct doca_ec *ec, doca_ec_task_recover_completion_cb_t successful_task_completion_cb, doca_ec_task_recover_completion_cb_t error_task_completion_cb, uint32_t num_tasks)
This method sets the recover tasks configuration.
DOCA_EXPERIMENTAL doca_error_t doca_ec_cap_get_max_block_size(const struct doca_devinfo *devinfo, uint64_t *max_block_size)
Get maximum block size supported for DOCA EC tasks.
DOCA_EXPERIMENTAL struct doca_task * doca_ec_task_create_as_task(struct doca_ec_task_create *task)
This method converts an EC create task to a doca_task.
DOCA_EXPERIMENTAL doca_error_t doca_ec_matrix_create_recover(struct doca_ec *ec, const struct doca_ec_matrix *coding_matrix, uint32_t missing_indices[], size_t n_missing, struct doca_ec_matrix **matrix)
Generate coding matrix for Erasure Code recovery from failure. To use this function must call doca_ec...
DOCA_EXPERIMENTAL doca_error_t doca_ec_matrix_create(struct doca_ec *ec, enum doca_ec_matrix_type type, size_t data_block_count, size_t rdnc_block_count, struct doca_ec_matrix **matrix)
Generate coding matrix for Erasure Code encode i.e. most basic encode matrix. This is necessary for e...
DOCA_EXPERIMENTAL struct doca_ctx * doca_ec_as_ctx(struct doca_ec *ec)
Convert EC instance into context.
DOCA_EXPERIMENTAL doca_error_t doca_ec_cap_task_recover_is_supported(const struct doca_devinfo *devinfo)
enum doca_error doca_error_t
DOCA API return codes.
DOCA_STABLE const char * doca_error_get_descr(doca_error_t error)
Returns the description string of an error code.
@ DOCA_ERROR_INVALID_VALUE
#define DOCA_LOG_ERR(format,...)
Generates an ERROR application log message.
#define DOCA_LOG_INFO(format,...)
Generates an INFO application log message.
DOCA_STABLE doca_error_t doca_mmap_set_memrange(struct doca_mmap *mmap, void *addr, size_t len)
Set the memory range of DOCA memory map.
DOCA_STABLE doca_error_t doca_mmap_start(struct doca_mmap *mmap)
Start DOCA Memory Map.
DOCA_STABLE doca_error_t doca_pe_connect_ctx(struct doca_pe *pe, struct doca_ctx *ctx)
This method connects a context to a progress engine.
DOCA_STABLE doca_error_t doca_task_submit(struct doca_task *task)
Submit a task to a progress engine.
DOCA_STABLE uint8_t doca_pe_progress(struct doca_pe *pe)
Run the progress engine.
DOCA_STABLE void doca_task_free(struct doca_task *task)
Free a task back to where it was allocated from.
DOCA_STABLE struct doca_ctx * doca_task_get_ctx(const struct doca_task *task)
Get context from a doca task.
doca_error_t(* tasks_check)(struct doca_devinfo *)
doca_error_t * task_status
struct doca_buf * rdnc_blocks
const char * output_dir_path
struct doca_buf * dst_doca_buf
struct program_core_objects core_state
uint32_t * missing_indices
struct doca_ec_matrix * decoding_matrix
struct doca_buf * src_doca_buf
struct doca_ec_matrix * encoding_matrix
struct doca_mmap * src_mmap
struct doca_buf_inventory * buf_inv
struct doca_mmap * dst_mmap
struct doca_buf * recovered_data_blocks
doca_error_t * task_status
uint32_t data_block_count
Convenience type for representing opaque data.
struct upf_accel_ctx * ctx
doca_error_t read_file(char const *path, char **out_bytes, size_t *out_bytes_len)