void mutation::copy_from(mutation_ptr& old) { data.updates = old->data.updates; client_requests = old->client_requests; _appro_data_bytes = old->_appro_data_bytes; _create_ts_ns = old->_create_ts_ns; for (auto& r : client_requests) { if (r != nullptr) { dsn_msg_add_ref(r); // release in dctor } } // let's always re-append the mutation to // replication logs as the ballot number // is changed, to ensure the invariance: // if decree(A) >= decree(B) // then ballot(A) >= ballot(B) /*if (old->is_logged()) { set_logged(); data.header.log_offset = old->data.header.log_offset; } */ _prepare_request = old->prepare_msg(); if (_prepare_request) { dsn_msg_add_ref(_prepare_request); } }
/*static*/ mutation_ptr mutation::read_from(binary_reader& reader, dsn_message_t from) { mutation_ptr mu(new mutation()); unmarshall(reader, mu->data); unmarshall(reader, mu->rpc_code); // it is possible this is an emtpy mutation due to new primaries inserts empty mutations for holes dassert(mu->data.updates.size() == 1 || mu->rpc_code == RPC_REPLICATION_WRITE_EMPTY, "batch is not supported now"); if (nullptr != from) { mu->_prepare_request = from; dsn_msg_add_ref(from); // released on dctor } else if (mu->data.updates.size() > 0) { dassert(mu->data.updates.at(0).has_holder(), "the buffer must has ownership"); } else { dassert(mu->rpc_code == RPC_REPLICATION_WRITE_EMPTY, "must be RPC_REPLICATION_WRITE_EMPTY"); } sprintf(mu->_name, "%lld.%lld", static_cast<long long int>(mu->data.header.ballot), static_cast<long long int>(mu->data.header.decree)); return mu; }
/*static*/ mutation_ptr mutation::read_from(binary_reader& reader, dsn_message_t from) { mutation_ptr mu(new mutation()); unmarshall(reader, mu->data, DSF_THRIFT_BINARY); for (const mutation_update& update : mu->data.updates) { dassert(update.code != TASK_CODE_INVALID, "invalid mutation task code"); } mu->client_requests.resize(mu->data.updates.size()); if (nullptr != from) { mu->_prepare_request = from; dsn_msg_add_ref(from); // released on dctor } snprintf_p(mu->_name, sizeof(mu->_name), "%" PRId32 ".%" PRId32 ".%" PRId64 ".%" PRId64, mu->data.header.pid.get_app_id(), mu->data.header.pid.get_partition_index(), mu->data.header.ballot, mu->data.header.decree); return mu; }
void mutation::add_client_request(task_code code, dsn_message_t request) { data.updates.push_back(mutation_update()); mutation_update& update = data.updates.back(); _appro_data_bytes += 32; // approximate code size if (request != nullptr) { update.code = code; dsn_msg_add_ref(request); // released on dctor void* ptr; size_t size; bool r = dsn_msg_read_next(request, &ptr, &size); dassert(r, "payload is not present"); dsn_msg_read_commit(request, 0); // so we can re-read the request buffer in replicated app update.data.assign((char*)ptr, 0, (int)size); _appro_data_bytes += sizeof(int) + (int)size; // data size } else { update.code = RPC_REPLICATION_WRITE_EMPTY; _appro_data_bytes += sizeof(int); // empty data size } client_requests.push_back(request); dassert(client_requests.size() == data.updates.size(), "size must be equal"); }
void mutation::copy_from(mutation_ptr& old) { data.updates = old->data.updates; rpc_code = old->rpc_code; if (old->is_logged()) { set_logged(); data.header.log_offset = old->data.header.log_offset; } _client_request = old->client_msg(); if (_client_request) { dsn_msg_add_ref(_client_request); } _prepare_request = old->prepare_msg(); if (_prepare_request) { dsn_msg_add_ref(_prepare_request); } }
void mutation::set_client_request(dsn_task_code_t code, dsn_message_t request) { dassert(_client_request == nullptr, "batch is not supported now"); rpc_code = code; if (request != nullptr) { _client_request = request; dsn_msg_add_ref(request); // released on dctor void* ptr; size_t size; bool r = dsn_msg_read_next(request, &ptr, &size); dassert(r, "payload is not present"); dsn_msg_read_commit(request, size); blob buffer((char*)ptr, 0, (int)size); data.updates.push_back(buffer); } }
/*static*/ mutation_ptr mutation::read_from_log_file(binary_reader& reader, dsn_message_t from) { mutation_ptr mu(new mutation()); unmarshall(reader, mu->data.header, DSF_THRIFT_BINARY); int size; unmarshall(reader, size, DSF_THRIFT_BINARY); mu->data.updates.resize(size); std::vector<int> lengths(size, 0); for (int i = 0; i < size; ++i) { unmarshall(reader, mu->data.updates[i].code, DSF_THRIFT_BINARY); unmarshall(reader, lengths[i], DSF_THRIFT_BINARY); } for (int i = 0; i < size; ++i) { int len = lengths[i]; std::shared_ptr<char> holder(new char[len], [](char* ptr){ delete []ptr; }); reader.read(holder.get(), len); mu->data.updates[i].data.assign(holder, 0, len); } mu->client_requests.resize(mu->data.updates.size()); if (nullptr != from) { mu->_prepare_request = from; dsn_msg_add_ref(from); // released on dctor } snprintf_p(mu->_name, sizeof(mu->_name), "%" PRId32 ".%" PRId32 ".%" PRId64 ".%" PRId64, mu->data.header.pid.get_app_id(), mu->data.header.pid.get_partition_index(), mu->data.header.ballot, mu->data.header.decree); return mu; }
void replica::on_update_configuration_on_meta_server_reply(error_code err, dsn_message_t request, dsn_message_t response, std::shared_ptr<configuration_update_request> req) { check_hashed_access(); if (PS_INACTIVE != status() || _stub->is_connected() == false) { _primary_states.reconfiguration_task = nullptr; err.end_tracking(); return; } configuration_update_response resp; if (err == ERR_OK) { ::unmarshall(response, resp); err = resp.err; } if (err != ERR_OK) { ddebug( "%s: update configuration reply with err %s, request ballot %lld", name(), err.to_string(), req->config.ballot ); if (err != ERR_INVALID_VERSION) { rpc_address target(_stub->_failure_detector->get_servers()); dsn_msg_add_ref(request); // added for another round of rpc::call _primary_states.reconfiguration_task = rpc::call( target, request, this, std::bind(&replica::on_update_configuration_on_meta_server_reply, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, req), gpid_to_hash(get_gpid()) ); return; } } ddebug( "%s: update configuration reply with err %s, ballot %lld, local %lld", name(), resp.err.to_string(), resp.config.ballot, get_ballot() ); if (resp.config.ballot < get_ballot()) { _primary_states.reconfiguration_task = nullptr; return; } // post-update work items? if (resp.err == ERR_OK) { dassert (req->config.gpid == resp.config.gpid, ""); dassert (req->config.app_type == resp.config.app_type, ""); dassert (req->config.primary == resp.config.primary, ""); dassert (req->config.secondaries == resp.config.secondaries, ""); switch (req->type) { case CT_UPGRADE_TO_PRIMARY: _primary_states.last_prepare_decree_on_new_primary = _prepare_list->max_decree(); break; case CT_ASSIGN_PRIMARY: case CT_DOWNGRADE_TO_SECONDARY: case CT_DOWNGRADE_TO_INACTIVE: case CT_UPGRADE_TO_SECONDARY: break; case CT_REMOVE: if (req->node != primary_address()) { replica_configuration rconfig; replica_helper::get_replica_config(resp.config, req->node, rconfig); rpc::call_one_way_typed(req->node, RPC_REMOVE_REPLICA, rconfig, gpid_to_hash(get_gpid())); } break; default: dassert (false, ""); } } update_configuration(resp.config); _primary_states.reconfiguration_task = nullptr; }