branch, trac-323-sos, updated. d929b66f24c75ce386a9cd780466db72a04ece1e
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "". The branch, trac-323-sos has been updated via d929b66f24c75ce386a9cd780466db72a04ece1e (commit) from 0622aa37a508132b868e2a3b8f3fc7e96ac9114d (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit d929b66f24c75ce386a9cd780466db72a04ece1e Author: John Jenkins <[email protected]> Date: Thu Mar 19 14:15:02 2015 -0500 initial record 'list IO' interface (untested) input: contiguous buffer, list of record IDs / record sizes ----------------------------------------------------------------------- Summary of changes: code/src/asg/asg-internal.ae | 108 +++++- code/src/asg/asg-internal.hae | 30 +- code/src/asg/asg-triton-ext.c | 9 +- code/src/asg/asg.c | 5 +- code/src/replicated-osd/rosd-read.ae | 15 + code/src/replicated-osd/rosd-write.ae | 762 ++++++++++++++++++++++++++++++++- code/src/replicated-osd/rosd.hae | 27 ++ 7 files changed, 908 insertions(+), 48 deletions(-) Diff of changes: diff --git a/code/src/asg/asg-internal.ae b/code/src/asg/asg-internal.ae index 2e5fb12..29c1556 100644 --- a/code/src/asg/asg-internal.ae +++ b/code/src/asg/asg-internal.ae @@ -123,7 +123,7 @@ __blocking int asg_i_write ( asg_flags_t flags, asg_update_id_t version_condition, asg_update_id_t * new_version, - const void * data, + void * data, asg_size_t * transferred) { triton_ret_t tret; @@ -154,6 +154,7 @@ __blocking int asg_i_write ( rosd_flags, version_condition, new_version, replication_factor); + /* TODO: handle short writes? */ if (triton_error_equal(tret, TRITON_ERR_CONDITIONAL)) aret = ASG_ERR_UPDATE_ID; else if (triton_is_error(tret)) @@ -182,7 +183,7 @@ __blocking int asg_i_read_sequence ( asg_size_t record_expected_len, asg_flags_t flags, asg_update_id_t update_id_condition, - const void * buf, + void * buf, asg_record_info_t * record_info) { triton_ret_t tret; @@ -749,7 +750,56 @@ __blocking int asg_i_read_set( asg_size_t * num_record_infos, asg_record_info_t * record_info) { - return ASG_ERR_OTHER; + triton_ret_t tret; + int aret; + uint32_t rosd_flags; + struct rosd_record_info *rinfo; + asg_size_t i; + + if (instance != 1) + return ASG_ERR_OTHER; + + rosd_flags = convert_flags_to_rosd(flags); + if (rosd_flags == -1 || rosd_flags == ROSD_COND_AUTO) + return ASG_ERR_INVAL; + + rinfo = malloc(sizeof(struct rosd_record_info) * num_records); + if (rinfo == NULL) + return ASG_ERR_OTHER; + + /* TODO: use safer casts */ + tret = remote_triton_rpc_rosd_read_set( + (uint64_t) container, + (uint64_t) object, + (uint64_t) fork, + (uint64_t) num_records, + (const uint64_t*) record_ids, + rosd_flags, + (uint64_t) update_id_condition, + buf, + buf_size, + (uint64_t*) num_record_infos, + rinfo); + + /* TODO: handle short reads? */ + if (triton_error_equal(tret, TRITON_ERR_CONDITIONAL)) + aret = ASG_ERR_UPDATE_ID; + else if (triton_is_error(tret)) { + triton_error_print(tret, "remote_triton_rpc_rosd_read_set"); + aret = ASG_ERR_OTHER; + } + else { + for (i = 0; i < *num_record_infos; i++) { + record_info[i].record_id = rinfo[i].record_id; + record_info[i].seq_len = rinfo[i].num_records; + record_info[i].record_len = rinfo[i].record_len; + record_info[i].record_update_id = rinfo[i].record_update_id; + } + aret = ASG_SUCCESS; + } + + triton_error_destroy(tret); + return aret; } __blocking int asg_i_write_set( @@ -759,15 +809,59 @@ __blocking int asg_i_write_set( asg_object_id_t object, asg_fork_id_t fork, asg_size_t num_records, - const asg_record_id_t * record_ids, - const asg_size_t * record_sizes, + asg_record_id_t * record_ids, + asg_size_t * record_sizes, asg_flags_t flags, asg_update_id_t update_id_condition, asg_update_id_t * new_update_id, - const void * buf, + void * buf, asg_size_t * records_written) { - return ASG_ERR_OTHER; + triton_ret_t tret; + int aret; + + uint32_t rosd_flags; + + const char * replication_factor_env; + uint32_t replication_factor; + + if (instance != 1) + return ASG_ERR_OTHER; + + /* hack: use environment variable to control the replication factor */ + replication_factor = 0; + replication_factor_env = getenv("TRITON_ASG_RF"); + if (replication_factor_env){ + if (0 == sscanf(replication_factor_env, "%d", &replication_factor)){ + /* simply ignore rather than returning something of interest */ + replication_factor = 0; + } + } + + rosd_flags = convert_flags_to_rosd(flags); + if (rosd_flags == -1) { + return ASG_ERR_INVAL; + } + + tret = remote_triton_rpc_rosd_write_set(container, object, fork, + num_records, record_ids, record_sizes, rosd_flags, + update_id_condition, new_update_id, buf, records_written, + replication_factor); + + /* TODO: how to handle short writes? */ + if (triton_error_equal(tret, TRITON_ERR_CONDITIONAL)) + aret = ASG_ERR_UPDATE_ID; + else if (triton_is_error(tret)) { + triton_error_print(tret, "remote_triton_rpc_rosd_write "); + triton_error_destroy(tret); + aret = ASG_ERR_OTHER; + } + else { + *records_written = num_records; + aret = ASG_SUCCESS; + } + + return aret; } /* diff --git a/code/src/asg/asg-internal.hae b/code/src/asg/asg-internal.hae index aa449d1..8c8fccd 100644 --- a/code/src/asg/asg-internal.hae +++ b/code/src/asg/asg-internal.hae @@ -43,7 +43,7 @@ __blocking int asg_i_write ( asg_flags_t flags, asg_update_id_t version_condition, asg_update_id_t * new_version, - const void * data, + void * data, asg_size_t * transferred); __blocking int asg_i_read_sequence ( @@ -57,7 +57,7 @@ __blocking int asg_i_read_sequence ( asg_size_t record_expected_len, asg_flags_t flags, asg_update_id_t update_id_condition, - const void * buf, + void * buf, asg_record_info_t * record_info); __blocking int asg_i_read_one ( @@ -173,19 +173,19 @@ __blocking int asg_i_read_set( asg_record_info_t * record_info); __blocking int asg_i_write_set( - asg_instance_t instance, - asg_location_t location, - asg_container_id_t container, - asg_object_id_t object, - asg_fork_id_t fork, - asg_size_t num_records, - const asg_record_id_t * record_ids, - const asg_size_t * record_sizes, - asg_flags_t flags, - asg_update_id_t update_id_condition, - asg_update_id_t * new_update_id, - const void * buf, - asg_size_t * records_written); + asg_instance_t instance, + asg_location_t location, + asg_container_id_t container, + asg_object_id_t object, + asg_fork_id_t fork, + asg_size_t num_records, + asg_record_id_t * record_ids, + asg_size_t * record_sizes, + asg_flags_t flags, + asg_update_id_t update_id_condition, + asg_update_id_t * new_update_id, + void * buf, + asg_size_t * records_written); #endif diff --git a/code/src/asg/asg-triton-ext.c b/code/src/asg/asg-triton-ext.c index 1d72065..1b39671 100644 --- a/code/src/asg/asg-triton-ext.c +++ b/code/src/asg/asg-triton-ext.c @@ -79,6 +79,8 @@ int asg_read_set( return aret; } +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-qual" /* write a set of records with possibly non-consecutive IDs */ int asg_write_set( asg_instance_t instance, @@ -99,8 +101,10 @@ int asg_write_set( asg_size_t i; ASG_HANDLE_AE_DEFAULT(asg_i_write_set, aret, instance, location, - container, object, fork, num_records, record_ids, record_sizes, - flags, update_id_condition, new_update_id, buf, records_written) + container, object, fork, num_records, + (asg_record_id_t*) record_ids, (asg_size_t*) record_sizes, + flags, update_id_condition, new_update_id, (void*) buf, + records_written) total_xfer = 0; if (aret == ASG_SUCCESS) { @@ -111,6 +115,7 @@ int asg_write_set( END_PROF(aret, "xfer:%lu", total_xfer) return aret; } +#pragma GCC diagnostic pop /* * Local variables: diff --git a/code/src/asg/asg.c b/code/src/asg/asg.c index b389828..ba8af25 100644 --- a/code/src/asg/asg.c +++ b/code/src/asg/asg.c @@ -112,6 +112,8 @@ int asg_read ( } #endif +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-qual" int asg_write ( asg_instance_t instance, asg_location_t location, @@ -129,10 +131,11 @@ int asg_write ( { ASG_HANDLE_AE_DEFAULT(asg_i_write, aret, instance, location, container, object, fork, start_record, recordcount, recordlen, flags, - version_condition, new_version, data, transferred) + version_condition, new_version, (void*) data, transferred) END_PROF(aret, "xfer:%lu", *transferred) return aret; } +#pragma GCC diagnostic pop int asg_punch ( asg_instance_t instance, diff --git a/code/src/replicated-osd/rosd-read.ae b/code/src/replicated-osd/rosd-read.ae index de5e2f0..6f141a7 100644 --- a/code/src/replicated-osd/rosd-read.ae +++ b/code/src/replicated-osd/rosd-read.ae @@ -221,6 +221,21 @@ __blocking triton_ret_t remote_triton_rpc_rosd_read_one( return tret; } +__blocking triton_ret_t remote_triton_rpc_rosd_read_set( + uint64_t container, + uint64_t object, + uint64_t fork, + uint64_t num_records, + const uint64_t * record_ids, + uint32_t flags, + uint64_t update_id_condition, + void * buf, + size_t buf_size, + uint64_t * num_record_infos, + struct rosd_record_info * record_info) { + return TRITON_ERR_NOT_IMPLEMENTED; +} + /* TODO: merge this with other functions */ static __blocking triton_ret_t rosd_read_one_local_storage( diff --git a/code/src/replicated-osd/rosd-write.ae b/code/src/replicated-osd/rosd-write.ae index 6985897..92da682 100644 --- a/code/src/replicated-osd/rosd-write.ae +++ b/code/src/replicated-osd/rosd-write.ae @@ -25,11 +25,13 @@ extern int64_t rosd_write_xfer_pipeline_depth; extern struct hoss_ctx* g_hoss_ctx; extern int64_t rosd_write_buffer_size; -/* Mercury RPC structures for rsos_write */ +extern struct buffer_mgmt_instance* rosd_write_buffers; + + +/* structures and declarations for rosd_write */ MERCURY_GEN_PROC(triton_rpc_rosd_write_out_t, ((triton_ret_t)(tret))\ ((uint64_t)(new_update_id))) - MERCURY_GEN_PROC(triton_rpc_rosd_write_in_t, ((uint64_t)(container))\ ((uint64_t)(object))\ @@ -42,8 +44,6 @@ MERCURY_GEN_PROC(triton_rpc_rosd_write_in_t, ((uint32_t)(expected_position))\ ((uint32_t)(replication_factor))\ ((hg_bulk_t)(bulk_handle))) - -extern struct buffer_mgmt_instance* rosd_write_buffers; static hg_id_t rpc_rosd_write_id; static __blocking triton_ret_t triton_rpc_rosd_write(hg_handle_t handle); static hg_return_t triton_rpc_rosd_write_handler(hg_handle_t handle); @@ -61,9 +61,6 @@ static __blocking triton_ret_t __remote_triton_rpc_rosd_write( uint64_t *new_update_id, uint32_t expected_position, uint32_t replication_factor); -static int is_usage_error_write(triton_ret_t tret); -static __blocking triton_ret_t resolve_replication_factor( - triton_rpc_rosd_write_in_t *in); static __blocking triton_ret_t rosd_write_do_work( na_addr_t next_addr, char* buffer, @@ -72,7 +69,6 @@ static __blocking triton_ret_t rosd_write_do_work( uint64_t recordcount, triton_rpc_rosd_write_in_t* in, uint64_t *new_update_id); - static __blocking triton_ret_t rosd_write_local_storage( uint64_t container, uint64_t object, @@ -85,6 +81,67 @@ static __blocking triton_ret_t rosd_write_local_storage( uint64_t update_id_condition, uint64_t *new_update_id); +/* structures and declarations for rosd_write_set */ +MERCURY_GEN_PROC(triton_rpc_rosd_write_set_out_t, + ((triton_ret_t)(tret)) \ + ((uint64_t)(new_update_id))) +MERCURY_GEN_PROC(triton_rpc_rosd_write_set_in_t, + ((uint64_t)(container)) \ + ((uint64_t)(object)) \ + ((uint64_t)(fork)) \ + ((uint64_t)(num_records)) \ + ((uint64_t)(update_id_condition)) \ + ((uint32_t)(flags)) \ + ((uint32_t)(expected_position)) \ + ((uint32_t)(replication_factor)) \ + ((hg_bulk_t)(bulk_handle))) +static hg_id_t rpc_rosd_write_set_id; +static __blocking triton_ret_t triton_rpc_rosd_write_set(hg_handle_t handle); +static hg_return_t triton_rpc_rosd_write_set_handler(hg_handle_t handle); +static __blocking triton_ret_t __remote_triton_rpc_rosd_write_set( + na_addr_t addr, + uint64_t container, + uint64_t object, + uint64_t fork, + uint64_t num_records, + uint64_t * record_ids, + uint64_t * record_sizes, + uint32_t flags, + uint64_t update_id_condition, + uint64_t * new_update_id, + void * buf, + uint64_t * records_written, + uint32_t expected_position, + uint32_t replication_factor); +static __blocking triton_ret_t rosd_write_set_do_work( + na_addr_t next_addr, + void * buffer, + int my_position, + uint64_t num_records, + uint64_t * record_ids, + uint64_t * record_sizes, + triton_rpc_rosd_write_set_in_t * in, + uint64_t *new_update_id); +static __blocking triton_ret_t rosd_write_set_local_storage( + uint64_t container, + uint64_t object, + uint64_t fork, + uint64_t num_records, + uint64_t * record_ids, + uint64_t * record_sizes, + void * buffer, + uint32_t flags, + uint64_t update_id_condition, + uint64_t *new_update_id); + +static int is_usage_error_write(triton_ret_t tret); +static __blocking triton_ret_t resolve_replication_factor( + uint64_t container, + uint64_t object, + uint32_t expected_position, + uint32_t * replication_factor, + uint32_t * flags); + __blocking triton_ret_t remote_triton_rpc_rosd_write( uint64_t container, uint64_t object, @@ -117,6 +174,37 @@ __blocking triton_ret_t remote_triton_rpc_rosd_write( } +__blocking triton_ret_t remote_triton_rpc_rosd_write_set( + uint64_t container, + uint64_t object, + uint64_t fork, + uint64_t num_records, + uint64_t * record_ids, + uint64_t * record_sizes, + uint32_t flags, + uint64_t update_id_condition, + uint64_t * new_update_id, + void * buf, + uint64_t * records_written, + uint32_t replication_factor) +{ + triton_ret_t tret; + na_addr_t addr; + int position; + + tret = triton_oid_to_addrs(object, 1, &position, &addr); + if (triton_is_error(tret)) + return tret; + + tret = __remote_triton_rpc_rosd_write_set(addr, container, object, fork, + num_records, record_ids, record_sizes, flags, update_id_condition, + new_update_id, buf, records_written, 0, replication_factor); + + triton_mercury_addr_free(addr); + + return tret; +} + static __blocking triton_ret_t rosd_handle_write_segment( hg_handle_t handle, na_addr_t src_addr, @@ -181,7 +269,84 @@ static __blocking triton_ret_t rosd_handle_write_segment( return(tret); } - + +static __blocking triton_ret_t rosd_handle_write_set_segment( + hg_handle_t handle, + na_addr_t src_addr, + na_addr_t next_addr, + int my_position, + triton_rpc_rosd_write_set_in_t* in, + uint64_t num_records, + uint64_t *record_ids, + uint64_t *record_sizes, + int64_t remote_offset, + uint64_t *new_update_id) +{ + void *buffer = NULL; + triton_ret_t tret; + int64_t outsize; + struct buffer_mgmt_token *token = NULL; + hg_bulk_t bulk_handle = HG_BULK_NULL; + int ret; + struct hg_info *info = NULL; + size_t bulk_size; + uint64_t i; + uint64_t total_rec_size = 0; + +#define FIN() \ + do { \ + if (token) buffer_mgmt_free(token); \ + if (bulk_handle != HG_BULK_NULL) HG_Bulk_free(bulk_handle); \ + } while(0) +#define END(_tret) \ + do { \ + FIN(); \ + return _tret; \ + } while(0) + + for (i = 0; i < num_records; i++) { + total_rec_size += record_sizes[i]; + } + + /* grab a buffer */ + tret = buffer_mgmt_alloc(rosd_write_buffers, total_rec_size, &outsize, + (char**)&buffer, &token); + if(tret != TRITON_SUCCESS) + END(tret); + assert(outsize == total_rec_size); + bulk_size = outsize; + + info = HG_Get_info(handle); + + /* set up and perform the bulk xfer */ + ret = HG_Bulk_create(info->hg_bulk_class, 1, &buffer, + &bulk_size, HG_BULK_WRITE_ONLY, &bulk_handle); + if (ret != HG_SUCCESS) { + triton_error_msg("HG_Bulk_create() failure\n"); + END(TRITON_ERR_NOMEM); + } + + ret = hg_rsc_bulk_transfer(info->bulk_context, HG_BULK_PULL, src_addr, + in->bulk_handle, remote_offset, bulk_handle, 0, bulk_size); + /* TODO: properly handle cancellations */ + assert(ret != AE_ERR_CANCELLED); + if (ret != HG_SUCCESS) { + triton_error_msg("hg_rsc_bulk_transfer() failure.\n"); + END(TRITON_ERR_UNKNOWN); + } + + tret = rosd_write_set_do_work(next_addr, buffer, my_position, num_records, + record_ids, record_sizes, in, new_update_id); + + FIN(); + return tret; +#undef FIN +#undef END +} + + + + static __blocking triton_ret_t rosd_write_run_pipeline( hg_handle_t handle, na_addr_t src_addr, @@ -282,8 +447,10 @@ static __blocking triton_ret_t rosd_write_run_pipeline( else if (is_update_id_set && *new_update_id != this_update_id) *new_update_id = ROSD_UPDATE_ID_MIXED; - else if (!is_update_id_set) + else if (!is_update_id_set) { *new_update_id = this_update_id; + is_update_id_set = 1; + } triton_mutex_unlock(&pipeline_mutex); } @@ -295,11 +462,179 @@ static __blocking triton_ret_t rosd_write_run_pipeline( return(out_tret); } +/* TODO: do better pipelining */ +static __blocking triton_ret_t rosd_write_set_run_pipeline( + hg_handle_t handle, + na_addr_t src_addr, + na_addr_t next_addr, + int my_position, + triton_rpc_rosd_write_set_in_t * in, + uint64_t * new_update_id) +{ + triton_ret_t out_tret; + triton_mutex_t pipeline_mutex; + int ret; + uint64_t current_record_pos = 0; + uint64_t current_bulk_offset = 0; + uint64_t current_remote_offset = 0; + int is_update_id_set = 0; + + /* HG specific vars */ + struct hg_info *info = NULL; + hg_bulk_t bulk_handle = HG_BULK_NULL; + + /* record bulk metadata (record sizes, ids) */ + uint64_t *rec_ptr; + uint64_t *rec_sizes; + uint64_t *rec_ids; + uint64_t rec_metadata_size; + size_t bulk_size; + +#define FIN() \ + do { \ + if (rec_ptr) free(rec_ptr); \ + if (bulk_handle != HG_BULK_NULL) HG_Bulk_free(bulk_handle); \ + triton_mutex_destroy(&pipeline_mutex); \ + } while (0) +#define END(_tret) \ + do { \ + FIN(); \ + return _tret; \ + } while (0) + + out_tret = TRITON_SUCCESS; + + triton_mutex_init(&pipeline_mutex, NULL); + + rec_metadata_size = 2 * in->num_records * sizeof(*rec_ptr); + + rec_ptr = malloc(rec_metadata_size); + if (rec_ptr) { + rec_ids = rec_ptr; + rec_sizes = rec_ptr + in->num_records; + } + else { + END(TRITON_ERR_NOMEM); + } + + bulk_size = rec_metadata_size; + ret = HG_Bulk_create(info->hg_bulk_class, 1, (void**)&rec_ptr, + &bulk_size, HG_BULK_WRITE_ONLY, &bulk_handle); + if (ret != HG_SUCCESS) { + triton_error_msg("HG_Bulk_create() failure.\n"); + END(TRITON_ERR_NOMEM); + } + + /* get the bulk metadata */ + hg_rsc_bulk_transfer(info->bulk_context, HG_BULK_PULL, src_addr, + in->bulk_handle, 0, bulk_handle, 0, rec_metadata_size); + /* TODO: properly handle cancellations */ + assert(ret != AE_ERR_CANCELLED); + if (ret != HG_SUCCESS) { + triton_error_msg("hg_rsc_bulk_transfer() failure.\n"); + END(TRITON_ERR_UNKNOWN); + } + + /* need to start off the remote offset as after the record metadata */ + current_remote_offset = rec_metadata_size; + + /* ready to start the pipeline */ + pwait + { + pprivate triton_ret_t b_tret; + pprivate int i, j; + pprivate int64_t pb_remote_offset; + pprivate uint64_t pb_record_count; + pprivate uint64_t pb_record_start_pos; + pprivate uint64_t pb_record_curr_pos; + pprivate uint64_t pb_total_size; + pprivate uint64_t pb_update_id; + for (i = 0; i < rosd_write_xfer_pipeline_depth; i++) { + pbranch + { + for (;;) { + /* calculate the next group of record indices + * [pb_record_start_pos, pb_record_curr_pos) */ + triton_mutex_lock(&pipeline_mutex); + if (current_record_pos >= in->num_records) { + triton_mutex_unlock(&pipeline_mutex); + pbreak; + } + pb_total_size = 0; + pb_record_count = 0; + pb_record_start_pos = current_record_pos; + pb_record_curr_pos = current_record_pos; + pb_remote_offset = current_remote_offset; + while (pb_record_curr_pos < in->num_records && + (pb_total_size + rec_sizes[pb_record_curr_pos] + <= rosd_write_buffer_size)) { + pb_total_size += rec_sizes[pb_record_curr_pos]; + pb_record_curr_pos++; + } + pb_record_count = pb_record_curr_pos - pb_record_start_pos; + if (pb_record_count == 0) { + triton_error_msg( + "record %lu's length of %lu is too large\n", + pb_record_curr_pos, + rec_sizes[pb_record_curr_pos]); + out_tret = TRITON_ERR_INVAL; + triton_mutex_unlock(&pipeline_mutex); + pbreak; + } + current_record_pos = pb_record_curr_pos; + current_remote_offset += pb_total_size; + + triton_mutex_unlock(&pipeline_mutex); + + /* we now have a lock on record indices + * [pb_record_start_pos, pb_record_curr_pos) */ + b_tret = rosd_handle_write_set_segment( + handle, + src_addr, + next_addr, + my_position, + in, + pb_record_count, + rec_ids + pb_record_start_pos, + rec_sizes + pb_record_start_pos, + pb_remote_offset, + &pb_update_id); + + triton_mutex_lock(&pipeline_mutex); + + if (triton_is_error(b_tret)) + out_tret = b_tret; + else if (is_update_id_set && + *new_update_id != pb_update_id) + *new_update_id = ROSD_UPDATE_ID_MIXED; + else if (!is_update_id_set) { + *new_update_id = pb_update_id; + is_update_id_set = 1; + } + + triton_mutex_unlock(&pipeline_mutex); + + } + } + } + } + + FIN(); + return out_tret; +#undef FIN +#undef END +} + /* This function validates the requested replication factor, storing it on * disk within the object if necessary + * replication_factor and flags are inout args */ static __blocking triton_ret_t resolve_replication_factor( - triton_rpc_rosd_write_in_t *in) + uint64_t container, + uint64_t object, + uint32_t expected_position, + uint32_t * replication_factor, + uint32_t * flags) { struct hoss_grp *grp; struct hoss_oid soid; @@ -313,8 +648,8 @@ static __blocking triton_ret_t resolve_replication_factor( /* go ahead and make the soid */ soid.nids = 3; soid.ids = soid_eids; - soid_eids[0] = in->container; - soid_eids[1] = in->object; + soid_eids[0] = container; + soid_eids[1] = object; soid_eids[2] = REP_FACTOR_FORK; /* TODO: check for "CANCELED" return code from hoss once supported. In @@ -328,7 +663,7 @@ static __blocking triton_ret_t resolve_replication_factor( return(TRITON_ERR_IO); } - if(in->expected_position == 0) + if(expected_position == 0) { /* This request is intended for the master. Validate replication * factor here against what is stored on disk (if present) @@ -340,9 +675,9 @@ static __blocking triton_ret_t resolve_replication_factor( { triton_debug(triton_dbg_rosd, "rosd_write() found on-disk replication factor of %d\n", ondisk_rep_factor); - if(in->replication_factor == 0) - in->replication_factor = ondisk_rep_factor; - else if(in->replication_factor != ondisk_rep_factor) + if(*replication_factor == 0) + *replication_factor = ondisk_rep_factor; + else if(*replication_factor != ondisk_rep_factor) { /* caller requested a replication factor that doesn't match * current replication for this object. @@ -354,22 +689,22 @@ static __blocking triton_ret_t resolve_replication_factor( } else { - in->flags |= ROSD_FLAG_FIRST_WRITE; + *flags |= ROSD_FLAG_FIRST_WRITE; } } - if(in->flags & ROSD_FLAG_FIRST_WRITE) + if(*flags & ROSD_FLAG_FIRST_WRITE) { /* store replication factor on disk */ /* this may happen on both master and replicas */ - if(in->replication_factor == 0) + if(*replication_factor == 0) { - in->replication_factor = rosd_default_replication_factor; + *replication_factor = rosd_default_replication_factor; ondisk_rep_factor = rosd_default_replication_factor; } else { - ondisk_rep_factor = in->replication_factor; + ondisk_rep_factor = *replication_factor; } triton_debug(triton_dbg_rosd, "rosd_write() writing on-disk replication factor of %d\n", ondisk_rep_factor); @@ -488,7 +823,8 @@ static __blocking triton_ret_t triton_rpc_rosd_write(hg_handle_t handle) out.tret = TRITON_ERR_CANCELED; while(triton_error_equal(out.tret, TRITON_ERR_CANCELED)) { - out.tret = resolve_replication_factor(&in); + out.tret = resolve_replication_factor(in.container, in.object, + in.expected_position, &in.replication_factor, &in.flags); } if(in.replication_factor > test_rep_factor) @@ -561,6 +897,118 @@ static __blocking triton_ret_t triton_rpc_rosd_write(hg_handle_t handle) } TRITON_DEFINE_RPC_HANDLER(triton_rpc_rosd_write) +static __blocking triton_ret_t triton_rpc_rosd_write_set(hg_handle_t handle) +{ + triton_rpc_rosd_write_set_out_t out; + triton_rpc_rosd_write_set_in_t in; + int ret = 0; + na_addr_t next_addr; + na_addr_t* addr_array; + int my_position; + na_addr_t src_addr; + struct hg_info *info = NULL; + int test_rep_factor; + +#define FIN() \ + do {\ + triton_mercury_respond(handle, &out); \ + HG_Destroy(handle); \ + if (addr_array) free(addr_array); \ + } while (0) + +#define END(_server_tret) \ + do { \ + FIN(); \ + return _server_tret; \ + } while (0) + + triton_debug(triton_dbg_rosd, "Called triton_rpc_rosd_write_set()\n"); + + addr_array = NULL; + info = HG_Get_info(handle); + src_addr = info->addr; + + triton_mercury_get_input(handle, &in, &out); + + triton_debug(triton_dbg_rosd, + "rosd_write_set() with incoming replication factor of %d " + "and incoming expected position of %d\n", + in.replication_factor, in.expected_position); + + /* downstream replicas must have rep. factor defined for them */ + if (in.expected_position != 0 && in.replication_factor == 0) { + out.tret = TRITON_ERR_INVAL; + triton_error_msg("ERROR: non-primary server " + "expected nonzero replication factor for \n"); + END(TRITON_ERR_INVAL); + } + /* no writing to "null" container/object/forks */ + else if (in.container == 0 || in.object == 0 || in.fork == 0) { + out.tret = TRITON_ERR_INVAL; + END(TRITON_SUCCESS); + } + /* if we're the primary, use rep factor of 1 just for testing purposes */ + else if (in.expected_position == 0) + test_rep_factor = 1; + else + test_rep_factor = in.replication_factor; + + addr_array = malloc(test_rep_factor*sizeof(*addr_array)); + if(!addr_array) { + out.tret = TRITON_ERR_NOMEM; + END(TRITON_SUCCESS); + } + + out.tret = triton_oid_to_addrs(in.object, test_rep_factor, &my_position, + addr_array); + if (triton_is_error(out.tret)) + END(TRITON_SUCCESS); + else if (my_position != in.expected_position) { + out.tret = TRITON_ERR_WRONG_SERVER; + END(TRITON_SUCCESS); + } + + /* check that the replication factor is valid and store on disk if needed */ + /* TODO: fix error codes; need to differentiate hoss canceled (which + * means we should retry) from aesop canceled (which means the operation + * has been explicitly canceled by another thread, likely due to error + * cleanup) */ + /* TODO: don't loop infinitely */ + out.tret = TRITON_ERR_CANCELED; + while (triton_error_equal(out.tret, TRITON_ERR_CANCELED)) + out.tret = resolve_replication_factor(in.container, in.object, + in.expected_position, &in.replication_factor, &in.flags); + + if (in.replication_factor > test_rep_factor) { + /* earlier rep factor assumption wrong, look up mapping again */ + free(addr_array); + addr_array = malloc(in.replication_factor * sizeof(*addr_array)); + if (!addr_array) { + out.tret = TRITON_ERR_NOMEM; + END(TRITON_SUCCESS); + } + + out.tret = triton_oid_to_addrs(in.object, in.replication_factor, + &my_position, addr_array); + if (triton_is_error(out.tret)) + END(TRITON_SUCCESS); + } + + if (my_position < in.replication_factor - 1) + next_addr = addr_array[my_position + 1]; + else + next_addr = NA_ADDR_NULL; + + out.tret = rosd_write_set_run_pipeline(handle, src_addr, next_addr, + my_position, &in, &out.new_update_id); + + FIN(); + return TRITON_SUCCESS; +#undef FIN +#undef END +} +TRITON_DEFINE_RPC_HANDLER(triton_rpc_rosd_write_set); + void triton_rpc_rosd_write_register(void) { hg_class_t* hg_class = NULL; @@ -572,6 +1020,11 @@ void triton_rpc_rosd_write_register(void) triton_rpc_rosd_write_in_t, triton_rpc_rosd_write_out_t, triton_rpc_rosd_write_handler); + rpc_rosd_write_set_id = + MERCURY_REGISTER(hg_class, "triton_rpc_rosd_write_set", + triton_rpc_rosd_write_set_in_t, + triton_rpc_rosd_write_set_out_t, + triton_rpc_rosd_write_handler); return; } @@ -622,6 +1075,73 @@ static __blocking triton_ret_t __remote_triton_rpc_rosd_write( return(tret); } +static __blocking triton_ret_t __remote_triton_rpc_rosd_write_set( + na_addr_t addr, + uint64_t container, + uint64_t object, + uint64_t fork, + uint64_t num_records, + uint64_t * record_ids, + uint64_t * record_sizes, + uint32_t flags, + uint64_t update_id_condition, + uint64_t * new_update_id, + void * buf, + uint64_t * records_written, + uint32_t expected_position, + uint32_t replication_factor) +{ + triton_rpc_rosd_write_set_out_t out; + triton_rpc_rosd_write_set_in_t in; + int ret; + triton_ret_t tret; + hg_handle_t handle = HG_HANDLE_NULL; + size_t bulk_size; + uint64_t i; + void * buffers[3]; + size_t buffer_sizes[3]; + + bulk_size = 0; + for (i = 0; i < num_records; i++) { + bulk_size += record_sizes[i]; + } + + in.container = container; + in.object = object; + in.fork = fork; + in.num_records = num_records; + in.flags = flags; + in.update_id_condition = update_id_condition; + in.expected_position = expected_position; + in.replication_factor = replication_factor; + in.bulk_handle = HG_BULK_NULL; + + /* set up the buffers for bulk transfer */ + buffers[0] = (void*) record_ids; + buffers[1] = (void*) record_sizes; + buffers[2] = (void*) buf; + + buffer_sizes[0] = num_records * sizeof(*record_ids); + buffer_sizes[1] = num_records * sizeof(*record_ids); + buffer_sizes[2] = bulk_size; + + triton_mercury_run_rpc_with_bulk(addr, rpc_rosd_write_set_id, handle, + &in, &out, in.bulk_handle, 3, buffers, buffer_sizes, 0, + HG_BULK_READ_ONLY); + + tret = triton_error_dup(out.tret); + + if (!triton_is_error(tret) || + triton_error_equal(tret, TRITON_ERR_CONDITIONAL)) + *new_update_id = out.new_update_id; + + HG_Free_output(handle, &out); + HG_Destroy(handle); + + return tret; +} + + static __blocking triton_ret_t rosd_write_do_work( na_addr_t next_addr, char* buffer, @@ -700,6 +1220,86 @@ static __blocking triton_ret_t rosd_write_do_work( return(tret); } +static __blocking triton_ret_t rosd_write_set_do_work( + na_addr_t next_addr, + void * buffer, + int my_position, + uint64_t num_records, + uint64_t * record_ids, + uint64_t * record_sizes, + triton_rpc_rosd_write_set_in_t * in, + uint64_t *new_update_id) +{ + + triton_ret_t local_tret; + triton_ret_t remote_tret = TRITON_SUCCESS; + triton_ret_t tret; + uint64_t new_update_id_local, new_update_id_remote; + uint64_t records_written_total = 0; + + /* right now only chained replication is supported */ + assert(!(in->flags & ROSD_FLAG_FANOUT)); + in->flags |= ROSD_FLAG_CHAIN; + + pwait + { + pprivate uint64_t records_written; + pbranch + { + /* forward on to peers if necessary */ + if(my_position < in->replication_factor-1) { + triton_debug(triton_dbg_rosd, + "ROSD forwarding write of oid %llu to %d'th server.\n", + llu(in->object), my_position+1); + + records_written = 0; + remote_tret = __remote_triton_rpc_rosd_write_set( + next_addr, in->container, in->object, in->fork, + num_records, record_ids, record_sizes, in->flags, + in->update_id_condition, new_update_id, buffer, + &records_written, my_position + 1, + in->replication_factor); + } + } + pbranch + { + triton_debug(triton_dbg_rosd, + "ROSD local write of oid %llu on %d'th server, " + "update_id %llu.\n", llu(in->object), my_position, + llu(in->update_id_condition)); + /* perform local operation */ + /* TODO: fix error codes; need to differentiate hoss canceled + * (which means we should retry) from aesop canceled (which means + * the operation has been explicitly canceled by another thread, + * likely due to error cleanup) + */ + local_tret = TRITON_ERR_CANCELED; + while(local_tret == TRITON_ERR_CANCELED) { + local_tret = rosd_write_set_local_storage( + in->container, in->object, in->fork, num_records, + record_ids, record_sizes, buffer, in->flags, + in->update_id_condition, &new_update_id_local); + } + } + } + + + if(my_position < in->replication_factor-1) + tret = interpret_errors(local_tret, remote_tret, my_position, + is_usage_error_write, !in->expected_position); + else + tret = interpret_error(local_tret, my_position, is_usage_error_write, + !in->expected_position); + + /* TODO: proper error checking for this */ + if (tret == TRITON_SUCCESS && my_position < in->replication_factor-1) { + assert(new_update_id_local == new_update_id_remote); + } + *new_update_id = new_update_id_local; + + return(tret); +} + /** * Checks the triton_ret_t to determine if the error code represents a * usage error rather than an a storage fault. Returns 1 if usage @@ -809,6 +1409,122 @@ static __blocking triton_ret_t rosd_write_local_storage( return(TRITON_SUCCESS); } +static __blocking triton_ret_t rosd_write_set_local_storage( + uint64_t container, + uint64_t object, + uint64_t fork, + uint64_t num_records, + uint64_t * record_ids, + uint64_t * record_sizes, + void * buffer, + uint32_t flags, + uint64_t update_id_condition, + uint64_t *new_update_id) +{ + struct hoss_grp *grp = NULL; + struct hoss_oid soid; + hoss_eid_t soid_eids[3]; + hoss_size_t *nbytes; + hoss_update_t update_in; + int ret, hoss_rc; + hoss_flags_t hoss_flags; + uint64_t i; + triton_ret_t tret; + + struct { + hoss_size_t nbytes; + int rc; + } * outputs; + +#define END(_tret)\ + do { \ + if (outputs) free(outputs); \ + if (grp) hoss_end(grp, 0); \ + return _tret; \ + } while (0) + + outputs = malloc(num_records * sizeof(*outputs)); + if (outputs == NULL) { + END(TRITON_ERR_NOMEM); + } + + /* TODO: handle canceled error code (or whatever hoss will report to + * indicate that a txn failed and should be retried) + */ + ret = hoss_begin(&grp, NULL, HOSS_MSYNC|HOSS_ORDERED|HOSS_DEFERRED, + g_hoss_ctx); + if(ret != 0) { + triton_error_msg("hoss_begin() failure (write)\n"); + END(TRITON_ERR_IO); + } + + soid.nids = 3; + soid.ids = soid_eids; + soid_eids[0] = container; + soid_eids[1] = object; + soid_eids[2] = fork; + + /* convert and sanity check the flags */ + hoss_flags = rosd_convert_flags_to_hoss(flags); + if (hoss_flags == -1) { + triton_error_msg( + "invalid ROSD flags passed in (should be caught earlier)\n"); + END(TRITON_ERR_INVAL); + } + + /* TODO: what to do when no update id is given */ + if (hoss_flags == HOSS_NONE) + update_in = 0; + else + update_in = update_id_condition; + + for (i = 0; i < num_records; i++) { + /* TODO: the update id arguments probably aren't right here... */ + ret = hoss_write(&soid, record_ids[i], 1, record_sizes[i], + hoss_flags, update_in, update_in, buffer, + grp, &outputs[i].nbytes, &outputs[i].rc); + if(ret != 0) { + triton_error_msg("hoss_write() failure, return code %d\n", ret); + END(TRITON_ERR_IO); + } + } + + ret = hoss_end(grp, 1); + grp = NULL; + + if (ret == HOSS_ECONDFAIL) { + END(TRITON_ERR_CONDITIONAL); + } + else if(ret != 0) { + triton_error_msg("hoss_end() failure (write), return code %d\n", ret); + END(TRITON_ERR_IO); + } + /* NOTE: output arguments to hoss_write (rc and nbytes) are not filled + * in until completion of hoss_end() + */ + else { + for (i = 0 ; i < num_records; i++) { + if (outputs[i].rc != 0 || outputs[i].nbytes != record_sizes[i]) { + triton_error_msg("hoss_write() failure, record %lu\n", + record_ids[i]); + END(TRITON_ERR_IO); + } + else if (outputs[i].nbytes != record_sizes[i]) { + triton_error_msg("hoss_write() failure (short write), " + "record %lu\n", record_ids[i]); + END(TRITON_ERR_IO); + } + } + } + + /* success */ + *new_update_id = update_in; + + return TRITON_SUCCESS; +#undef END +} + + /* * Local Variables: diff --git a/code/src/replicated-osd/rosd.hae b/code/src/replicated-osd/rosd.hae index 6d47f12..1a23317 100644 --- a/code/src/replicated-osd/rosd.hae +++ b/code/src/replicated-osd/rosd.hae @@ -102,6 +102,20 @@ __blocking triton_ret_t remote_triton_rpc_rosd_write( uint64_t *new_update_id, uint32_t replication_factor); +__blocking triton_ret_t remote_triton_rpc_rosd_write_set( + uint64_t container, + uint64_t object, + uint64_t fork, + uint64_t num_records, + uint64_t * record_ids, + uint64_t * record_sizes, + uint32_t flags, + uint64_t update_id_condition, + uint64_t * new_update_id, + void * buf, + uint64_t * records_written, + uint32_t replication_factor); + __blocking triton_ret_t remote_triton_rpc_rosd_read_sequence( uint64_t container, uint64_t object, @@ -126,6 +140,19 @@ __blocking triton_ret_t remote_triton_rpc_rosd_read_one( uint64_t * record_len, uint64_t * record_update_id); +__blocking triton_ret_t remote_triton_rpc_rosd_read_set( + uint64_t container, + uint64_t object, + uint64_t fork, + uint64_t num_records, + const uint64_t * record_ids, + uint32_t flags, + uint64_t update_id_condition, + void * buf, + size_t buf_size, + uint64_t * num_record_infos, + struct rosd_record_info * record_info); + __blocking triton_ret_t rosd_pipeline_setup_one_buffer( struct buffer_mgmt_instance* buffer_instance, aesop_sem_t *sem, hooks/post-receive --
participants (1)
-
noreply@mcs.anl.gov