void McServerTransaction::onMultigetReply(McReply& subReply) { assert(isMultiget_); /* If not a hit or a miss, and we didn't store a reply yet, steal it */ if (!(subReply.result() == mc_res_found || subReply.result() == mc_res_notfound) && (!reply_.hasValue() || (subReply.result() > reply_->result()))) { reply_ = std::move(subReply); } assert(numMultiget_ > 0); --numMultiget_; if (!numMultiget_) { if (!reply_.hasValue()) { reply_ = McReply(mc_res_found); } replyReady_ = true; session_->onRequestReplied(*this); } }
bool UmbrellaSerializedMessage::prepare(const McReply& reply, mc_op_t op, uint64_t reqid, struct iovec*& iovOut, size_t& niovOut) { niovOut = 0; appendInt(I32, msg_op, umbrella_op_from_mc[op]); appendInt(U64, msg_reqid, reqid); appendInt(I32, msg_result, umbrella_res_from_mc[reply.result()]); if (reply.appSpecificErrorCode()) { appendInt(I32, msg_err_code, reply.appSpecificErrorCode()); } if (reply.flags()) { appendInt(U64, msg_flags, reply.flags()); } if (reply.exptime()) { appendInt(U64, msg_exptime, reply.exptime()); } if (reply.delta()) { appendInt(U64, msg_delta, reply.delta()); } if (reply.leaseToken()) { appendInt(U64, msg_lease_id, reply.leaseToken()); } if (reply.cas()) { appendInt(U64, msg_cas, reply.cas()); } if (reply.number()) { appendInt(U64, msg_number, reply.number()); } /* TODO: if we intend to pass chained IOBufs as values, we can optimize this to write multiple iovs directly */ if (reply.hasValue()) { auto valueRange = reply.valueRangeSlow(); appendString(msg_value, reinterpret_cast<const uint8_t*>(valueRange.begin()), valueRange.size()); } /* NOTE: this check must come after all append*() calls */ if (error_) { return false; } niovOut = finalizeMessage(); iovOut = iovs_; return true; }
bool McServerRequestContext::noReply(const McReply& reply) const { if (noReply_) { return true; } if (!parent_) { return false; } /* No reply if either: 1) We saw an error (the error will be printed out by the end context) 2) This is a miss, except for lease_get (lease get misses still have 'LVALUE' replies with the token) */ return (parent_->error() || !(reply.result() == mc_res_found || operation_ == mc_op_lease_get)); }
void DestinationClient::onReply(McReply reply, mc_op_t op, void* req_ctx, std::weak_ptr<ProxyDestination> pdstn) { auto pdstnPtr = pdstn.lock(); // ProxyDestination is already dead, just return. if (!pdstnPtr) { return; } auto proxy = pdstnPtr->proxy; if (reply.result() == mc_res_local_error) { update_send_stats(proxy, op, PROXY_SEND_LOCAL_ERROR); } else { stat_incr(proxy->stats, sum_server_queue_length_stat, 1); update_send_stats(proxy, op, PROXY_SEND_OK); } pdstnPtr->on_reply(std::move(reply), req_ctx); }
bool UmbrellaSerializedReply::prepare(const McReply& reply, mc_op_t op, uint64_t reqid, struct iovec*& iovOut, size_t& niovOut) { static char nul = '\0'; /* We can reuse this struct multiple times, reset the counters */ nEntries_ = nStrings_ = offset_ = 0; error_ = false; niovOut = 0; appendInt(I32, msg_op, umbrella_op_from_mc[op]); appendInt(U64, msg_reqid, reqid); appendInt(I32, msg_result, umbrella_res_from_mc[reply.result()]); if (reply.appSpecificErrorCode()) { appendInt(I32, msg_err_code, reply.appSpecificErrorCode()); } if (reply.flags()) { appendInt(U64, msg_flags, reply.flags()); } if (reply.exptime()) { appendInt(U64, msg_exptime, reply.exptime()); } if (reply.delta()) { appendInt(U64, msg_delta, reply.delta()); } if (reply.leaseToken()) { appendInt(U64, msg_lease_id, reply.leaseToken()); } if (reply.cas()) { appendInt(U64, msg_cas, reply.cas()); } if (reply.lowValue() || reply.highValue()) { appendDouble(reply.lowValue()); } if (reply.highValue()) { appendDouble(reply.highValue()); } /* TODO: if we intend to pass chained IOBufs as values, we can optimize this to write multiple iovs directly */ if (reply.hasValue()) { auto valueRange = reply.valueRangeSlow(); appendString(msg_value, reinterpret_cast<const uint8_t*>(valueRange.begin()), valueRange.size()); } /* NOTE: this check must come after all append*() calls */ if (error_) { return false; } size_t size = sizeof(entry_list_msg_t) + sizeof(um_elist_entry_t) * nEntries_ + offset_; msg_.total_size = folly::Endian::big((uint32_t)size); msg_.nentries = folly::Endian::big((uint16_t)nEntries_); iovs_[1].iov_len = sizeof(um_elist_entry_t) * nEntries_; niovOut = 2; for (size_t i = 0; i < nStrings_; i++) { iovs_[niovOut].iov_base = (char *)strings_[i].begin(); iovs_[niovOut].iov_len = strings_[i].size(); niovOut++; iovs_[niovOut].iov_base = &nul; iovs_[niovOut].iov_len = 1; niovOut++; } iovOut = iovs_; return true; }