void CaretReplyConverter::onTypedMessage(
    TypedThriftReply<cpp2::McMetagetReply>&& tres, McReply& reply) {

  if (!fillResult(tres, reply)) {
    return;
  }

  if (tres->__isset.age) {
    reply.setNumber(tres->age);
  }
  if (tres->__isset.exptime) {
    reply.setExptime(tres->exptime);
  }
  struct in6_addr addr;

  if (tres->__isset.ipAddress) {
    if (!tres->__isset.ipv) {
      reply.setResult(mc_res_bad_value);
      return;
    }
    int af = (tres->ipv == 6) ? AF_INET6 : AF_INET;
    auto ret = inet_pton(
        af, reinterpret_cast<const char*>(tres->ipAddress.data()), &addr);
    if (ret == 1) {
      reply.setIpAddress(addr, tres->ipv);
    }
  }
}
void CaretReplyConverter::onTypedMessage(
    TypedThriftReply<cpp2::McVersionReply>&& tres, McReply& reply) {
  if (!fillResult(tres, reply)) {
    return;
  }
  if (tres->__isset.value != true) {
    reply.setResult(mc_res_bad_value);
    return;
  }
  reply.setValue(std::move(tres->value));
}
void CaretReplyConverter::onTypedMessage(
    TypedThriftReply<cpp2::McLeaseGetReply>&& tres, McReply& reply) {
  if (tres->__isset.leaseToken) {
    reply.setLeaseToken(tres->leaseToken);
  }
  onGetCommon(std::move(tres), reply);
}
void CaretReplyConverter::onTypedMessage(
    TypedThriftReply<cpp2::McDeleteReply>&& tres, McReply& reply) {
  if (tres->get_value()) {
    reply.setValue(std::move(tres->value));
  }
  fillResult(tres, reply);
}
void CaretReplyConverter::onTypedMessage(
    TypedThriftReply<cpp2::McSetReply>&& tres, McReply& reply) {
  if (tres->get_value()) {
    reply.setValue(std::move(tres->value));
  }
  onUpdateCommon(std::move(tres), reply);
}
void CaretReplyConverter::onTypedMessage(
    TypedThriftReply<cpp2::McGetsReply>&& tres, McReply& reply) {
  if (tres->__isset.casToken) {
    reply.setCas(tres->casToken);
  }
  onGetCommon(std::move(tres), reply);
}
示例#7
0
bool AsciiSerializedReply::prepare(const McReply& reply,
                                   mc_op_t operation,
                                   const folly::Optional<folly::IOBuf>& key,
                                   struct iovec*& iovOut, size_t& niovOut) {
  mc_msg_t replyMsg;
  mc_msg_init_not_refcounted(&replyMsg);
  reply.dependentMsg(operation, &replyMsg);

  nstring_t k;
  if (key.hasValue()) {
    k.str = (char*)key->data();
    k.len = key->length();
  } else {
    k.str = nullptr;
    k.len = 0;
  }
  niovOut = mc_ascii_response_write_iovs(
    &asciiResponse_,
    k,
    operation,
    &replyMsg,
    iovs_,
    kMaxIovs);
  iovOut = iovs_;
  return niovOut != 0;
}
示例#8
0
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 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));
}
示例#10
0
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;
}
示例#12
0
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;
}