static as_status as_command_parse_udf_failure(uint8_t* p, as_error* err, as_msg* msg, as_status status) { p = as_command_ignore_fields(p, msg->n_fields); as_bin_name name; for (uint32_t i = 0; i < msg->n_ops; i++) { uint32_t op_size = cf_swap_from_be32(*(uint32_t*)p); p += 5; uint8_t type = *p; p += 2; uint8_t name_size = *p++; uint8_t name_len = (name_size <= AS_BIN_NAME_MAX_LEN)? name_size : AS_BIN_NAME_MAX_LEN; memcpy(name, p, name_len); name[name_len] = 0; p += name_size; uint32_t value_size = (op_size - (name_size + 4)); if (strcmp(name, "FAILURE") == 0) { as_val* val = 0; as_command_parse_value(p, type, value_size, &val); status = as_command_parse_udf_error(err, status, val); as_val_destroy(val); return status; } p += value_size; } return as_error_set_message(err, status, as_error_string(status)); }
as_status as_command_parse_success_failure_bins(uint8_t** pp, as_error* err, as_msg* msg, as_val** value) { uint8_t* p = *pp; p = as_command_ignore_fields(p, msg->n_fields); as_bin_name name; for (uint32_t i = 0; i < msg->n_ops; i++) { uint32_t op_size = cf_swap_from_be32(*(uint32_t*)p); p += 5; uint8_t type = *p; p += 2; uint8_t name_size = *p++; uint8_t name_len = (name_size <= AS_BIN_NAME_MAX_LEN)? name_size : AS_BIN_NAME_MAX_LEN; memcpy(name, p, name_len); name[name_len] = 0; p += name_size; uint32_t value_size = (op_size - (name_size + 4)); if (strcmp(name, "SUCCESS") == 0) { if (value) { as_command_parse_value(p, type, value_size, value); } *pp = p + value_size; return AEROSPIKE_OK; } if (strcmp(name, "FAILURE") == 0) { as_val* val = 0; as_command_parse_value(p, type, value_size, &val); if (val == 0) { as_error_set_message(err, AEROSPIKE_ERR_CLIENT, "Received null FAILURE bin."); } else if (val->type == AS_STRING) { as_error_set_message(err, AEROSPIKE_ERR_CLIENT, ((as_string*)val)->value); } else { as_error_update(err, AEROSPIKE_ERR_CLIENT, "Expected string for FAILURE bin. Received %d", val->type); } as_val_destroy(val); return err->code; } p += value_size; } return as_error_set_message(err, AEROSPIKE_ERR_CLIENT, "Failed to find SUCCESS or FAILURE bin."); }
bool as_event_command_parse_result(as_event_command* cmd) { as_msg* msg = (as_msg*)cmd->buf; as_msg_swap_header_from_be(msg); uint8_t* p = cmd->buf + sizeof(as_msg); as_status status = msg->result_code; switch (status) { case AEROSPIKE_OK: { as_record rec; if (msg->n_ops < 1000) { as_record_inita(&rec, msg->n_ops); } else { as_record_init(&rec, msg->n_ops); } rec.gen = msg->generation; rec.ttl = cf_server_void_time_to_ttl(msg->record_ttl); p = as_command_ignore_fields(p, msg->n_fields); as_command_parse_bins(&rec, p, msg->n_ops, cmd->deserialize); as_event_response_complete(cmd); ((as_async_record_command*)cmd)->listener(0, &rec, cmd->udata, cmd->event_loop); as_event_command_release(cmd); as_record_destroy(&rec); break; } case AEROSPIKE_ERR_UDF: { as_error err; as_command_parse_udf_failure(p, &err, msg, status); as_event_response_error(cmd, &err); break; } default: { as_error err; as_error_set_message(&err, status, as_error_string(status)); as_event_response_error(cmd, &err); break; } } return true; }
as_status as_command_parse_result(as_error* err, int fd, uint64_t deadline_ms, void* user_data) { // Read header as_proto_msg msg; as_status status = as_socket_read_deadline(err, fd, (uint8_t*)&msg, sizeof(as_proto_msg), deadline_ms); if (status) { return status; } as_proto_swap_from_be(&msg.proto); as_msg_swap_header_from_be(&msg.m); size_t size = msg.proto.sz - msg.m.header_sz; uint8_t* buf = 0; if (size > 0) { // Read remaining message bytes. buf = as_command_init(size); status = as_socket_read_deadline(err, fd, buf, size, deadline_ms); if (status) { as_command_free(buf, size); return status; } } // Parse result code and record. status = msg.m.result_code; as_command_parse_result_data* data = user_data; switch (status) { case AEROSPIKE_OK: { if (data->record) { as_record* rec = *data->record; if (rec) { if (msg.m.n_ops > rec->bins.capacity) { if (rec->bins._free) { free(rec->bins.entries); } rec->bins.capacity = msg.m.n_ops; rec->bins.size = 0; rec->bins.entries = malloc(sizeof(as_bin) * msg.m.n_ops); rec->bins._free = true; } } else { rec = as_record_new(msg.m.n_ops); *data->record = rec; } rec->gen = msg.m.generation; rec->ttl = cf_server_void_time_to_ttl(msg.m.record_ttl); uint8_t* p = as_command_ignore_fields(buf, msg.m.n_fields); as_command_parse_bins(rec, p, msg.m.n_ops, data->deserialize); } break; } case AEROSPIKE_ERR_UDF: { status = as_command_parse_udf_failure(buf, err, &msg.m, status); break; } default: as_error_set_message(err, status, as_error_string(status)); break; } as_command_free(buf, size); return status; }