Ejemplo n.º 1
0
static void
req_forward_remote_dc(struct context *ctx, struct conn *c_conn, struct msg *msg,
                      struct mbuf *orig_mbuf, uint8_t *key, uint32_t keylen,
                      struct datacenter *dc)
{
    uint32_t rack_cnt = array_n(&dc->racks);
    if (rack_cnt == 0)
        return;

    struct rack *rack = dc->preselected_rack_for_replication;
    if (rack == NULL)
        rack = array_get(&dc->racks, 0);

    struct msg *rack_msg = msg_get(c_conn, msg->request, __FUNCTION__);
    if (rack_msg == NULL) {
        log_debug(LOG_VERB, "whelp, looks like yer screwed now, buddy. no inter-rack messages for you!");
        msg_put(rack_msg);
        return;
    }

    msg_clone(msg, orig_mbuf, rack_msg);
    log_info("msg (%d:%d) clone to remote rack msg (%d:%d)",
            msg->id, msg->parent_id, rack_msg->id, rack_msg->parent_id);
    rack_msg->swallow = true;

    if (log_loggable(LOG_DEBUG)) {
        log_debug(LOG_DEBUG, "forwarding request to conn '%s' on rack '%.*s'",
                dn_unresolve_peer_desc(c_conn->sd), rack->name->len, rack->name->data);
    }
    remote_req_forward(ctx, c_conn, rack_msg, rack, key, keylen);
}
Ejemplo n.º 2
0
/**Forward a request.
 *
 * @deprecated
 * Use nta_outgoing_mcreate() instead.
 */
nta_outgoing_t *nta_outgoing_tclone(nta_agent_t *agent,
				    nta_response_f *callback,
				    nta_outgoing_magic_t *magic,
				    url_string_t const *route_url,
				    msg_t *parent,
				    tag_type_t tag, tag_value_t value, ...)
{
  ta_list ta;
  msg_t *msg;
  nta_outgoing_t *orq = NULL;

  if (parent == NULL)
    return NULL;
  if ((msg = nta_msg_create(agent, 0)) == NULL)
    return NULL;

  ta_start(ta, tag, value);

  msg_clone(msg, parent);

  if (parent && sip_copy_all(msg, sip_object(msg), sip_object(parent)) < 0)
    ;
  else if (sip_add_tl(msg, sip_object(msg), ta_tags(ta)) < 0)
    ;
  else
    orq = nta_outgoing_mcreate(agent, callback, magic, route_url, msg); 

  ta_end(ta);

  if (!orq)
    msg_destroy(msg);

  return orq;
  
}
Ejemplo n.º 3
0
/** Fork an outgoing request (stdarg version of nta_outgoing_fork()). 
 *
 * @deprecated
 * Use nta_outgoing_mcreate() instead.
 */
nta_outgoing_t *nta_outgoing_vfork(nta_outgoing_t *old_orq,
				   nta_response_f *callback,
				   nta_outgoing_magic_t *magic,
				   url_string_t const *route_url,
				   url_string_t const *request_uri,
				   void const *extra,
				   va_list headers)
{
  nta_outgoing_t * orq;
  msg_t *msg, *imsg;
  sip_t *sip, *isip;
  nta_agent_t *agent;
  su_home_t *home;

  if (!old_orq || !old_orq->orq_request || !request_uri)
    return NULL;

  agent = old_orq->orq_agent;
  imsg = old_orq->orq_request;
  
  if (!(msg = nta_msg_create(agent, 0)))
    return NULL;

  msg_clone(msg, imsg);

  sip = sip_object(msg); isip = sip_object(imsg);
  home = msg_home(msg);

  /* Copy the SIP headers from the imsg message */
  if (sip_copy_all(msg, sip, isip) < 0)
    orq = NULL;
  else if (sip_via_remove(msg, sip) == NULL)
    orq = NULL;
  else if (sip_add_dup(msg, sip_object(msg), 
		       (sip_header_t const *)
		       sip_request_create(home,
					  sip->sip_request->rq_method, 
					  sip->sip_request->rq_method_name, 
					  request_uri,
					  NULL)) < 0)
    orq = NULL;
  else if (sip_add_headers(msg, sip, extra, headers) < 0)
    orq = NULL;
  else
    orq = nta_outgoing_mcreate(agent, callback, magic, route_url, msg);

  if (!orq)
    msg_destroy(msg);

  return orq;
}
Ejemplo n.º 4
0
/**Get request message.
 *
 * The function nta_outgoing_getrequest() retrieves the request message sent
 * to the network. The request message is copied; the original copy is kept
 * by the transaction.
 *
 * @param orq outgoing transaction handle
 *
 * @retval
 * A pointer to the copy of the request message is returned, or NULL if an
 * error occurred.
 */
msg_t *nta_outgoing_getrequest(nta_outgoing_t *orq)
{
  if (orq && orq->orq_request) {
    msg_t *msg = nta_msg_create(orq->orq_agent, 0);
    sip_t *sip = sip_object(msg);

    msg_clone(msg, orq->orq_request);

    /* Copy the SIP headers from the old message */
    if (sip_copy_all(msg, sip, sip_object(orq->orq_request)) >= 0)
      return msg;

    msg_destroy(msg);
  }

  return NULL;
}
Ejemplo n.º 5
0
/**Get response message.
 *
 * The function nta_incoming_getresponse() retrieves a copy of the latest
 * outgoing response message.  The response message is copied; the original
 * copy is kept by the transaction.
 *
 * @param irq incoming (server) transaction handle
 *
 * @retval
 * A pointer to the copy of the response message is returned, or NULL if an
 * error occurred.
 */
msg_t *nta_incoming_getresponse(nta_incoming_t *irq)
{
  if (irq && irq->irq_response) {
    msg_t *msg = nta_msg_create(irq->irq_agent, 0);
    sip_t *sip = sip_object(msg);

    msg_clone(msg, irq->irq_response);

    /* Copy the SIP headers from the old message */
    if (msg_copy_all(msg, sip, sip_object(irq->irq_response)) >= 0)
      return msg;

    msg_destroy(msg);
  }

  return NULL;
}
Ejemplo n.º 6
0
static void
req_forward_all_local_racks(struct context *ctx, struct conn *c_conn,
                            struct msg *msg, struct mbuf *orig_mbuf,
                            uint8_t *key, uint32_t keylen, struct datacenter *dc)
{
    //log_debug(LOG_DEBUG, "dc name  '%.*s'",
    //            dc->name->len, dc->name->data);
    uint8_t rack_cnt = (uint8_t)array_n(&dc->racks);
    uint8_t rack_index;
    msg->rsp_handler = msg_get_rsp_handler(msg);
    init_response_mgr(&msg->rspmgr, msg, msg->is_read, rack_cnt, c_conn);
    log_info("msg %d:%d same DC racks:%d expect replies %d",
             msg->id, msg->parent_id, rack_cnt, msg->rspmgr.max_responses);
    for(rack_index = 0; rack_index < rack_cnt; rack_index++) {
        struct rack *rack = array_get(&dc->racks, rack_index);
        //log_debug(LOG_DEBUG, "rack name '%.*s'",
        //            rack->name->len, rack->name->data);
        struct msg *rack_msg;
        // clone message even for local node
        struct server_pool *pool = c_conn->owner;
        if (string_compare(rack->name, &pool->rack) == 0 ) {
            rack_msg = msg;
        } else {
            rack_msg = msg_get(c_conn, msg->request, __FUNCTION__);
            if (rack_msg == NULL) {
                log_debug(LOG_VERB, "whelp, looks like yer screwed "
                        "now, buddy. no inter-rack messages for "
                        "you!");
                continue;
            }

            msg_clone(msg, orig_mbuf, rack_msg);
            log_info("msg (%d:%d) clone to rack msg (%d:%d)",
                     msg->id, msg->parent_id, rack_msg->id, rack_msg->parent_id);
            rack_msg->swallow = true;
        }

        if (log_loggable(LOG_DEBUG)) {
            log_debug(LOG_DEBUG, "forwarding request to conn '%s' on rack '%.*s'",
                    dn_unresolve_peer_desc(c_conn->sd), rack->name->len, rack->name->data);
        }
        log_debug(LOG_VERB, "c_conn: %p forwarding (%d:%d)",
                c_conn, rack_msg->id, rack_msg->parent_id);
        remote_req_forward(ctx, c_conn, rack_msg, rack, key, keylen);
    }
}
Ejemplo n.º 7
0
/**Forward a request belonging to the leg 
 * (stdarg version of nta_outgoing_forward()).
 *
 * @deprecated
 * Use nta_outgoing_mcreate() instead.
 */
nta_outgoing_t *nta_outgoing_vforward(nta_leg_t *leg,
				      nta_response_f *callback,
				      nta_outgoing_magic_t *magic,
				      url_string_t const *route_url,
				      url_string_t const *request_uri,
				      nta_incoming_t const *ireq,
				      sip_t const *isip,
				      void const *extra,
				      va_list headers)
{
  nta_agent_t *agent = leg->leg_agent;
  nta_outgoing_t *orq = NULL;
  msg_t *msg, *imsg;
  sip_t *sip;
  su_home_t *home;

  assert(leg); assert(ireq); 

  if (isip == NULL) 
    imsg = ireq->irq_request, isip = sip_object(ireq->irq_request);
  else if (isip == sip_object(ireq->irq_request))
    imsg = ireq->irq_request;
  else if (isip == sip_object(ireq->irq_request2))
    imsg = ireq->irq_request2;
  else {
    SU_DEBUG_3(("nta_outgoing_forward: invalid arguments\n"));
    return NULL;
  }

  assert(isip); assert(isip->sip_request);

  if (!route_url)
    route_url = (url_string_t *)agent->sa_default_proxy;

  if (!(msg = nta_msg_create(agent, 0)))
    return NULL;

  msg_clone(msg, imsg);

  sip = sip_object(msg); 
  home = msg_home(msg);
  
  /* Copy the SIP headers from the @c imsg message */
  do {
    if (sip_copy_all(msg, sip, isip) < 0)
      break;
    if (sip_add_headers(msg, sip, extra, headers) < 0)
      break;
    if (!route_url && sip->sip_route) {
      request_uri = (url_string_t *)sip->sip_route->r_url;
      if (!sip_route_remove(msg, sip))
	break;
    }
    if (request_uri) {
      sip_request_t *rq;

      rq = sip_request_create(home,
			      sip->sip_request->rq_method, 
			      sip->sip_request->rq_method_name, 
			      request_uri,
			      NULL);

      if (!rq || sip_header_insert(msg, sip, (sip_header_t *)rq) < 0)
	break;
    }
    
    if ((orq = nta_outgoing_mcreate(agent, callback, magic, route_url, msg)))
      return orq;

  } while (0);

  msg_destroy(msg);
  return NULL;
}
Ejemplo n.º 8
0
static void
dnode_req_forward(struct context *ctx, struct conn *conn, struct msg *msg)
{
    struct server_pool *pool;
    uint8_t *key;
    uint32_t keylen;

    if (log_loggable(LOG_DEBUG)) {
       log_debug(LOG_DEBUG, "dnode_req_forward entering ");
    }
    log_debug(LOG_DEBUG, "DNODE REQ RECEIVED %s %d dmsg->id %u",
              conn_get_type_string(conn), conn->sd, msg->dmsg->id);

    ASSERT(conn->type == CONN_DNODE_PEER_CLIENT);

    pool = conn->owner;
    key = NULL;
    keylen = 0;

    log_debug(LOG_DEBUG, "conn %p adding message %d:%d", conn, msg->id, msg->parent_id);
    dictAdd(conn->outstanding_msgs_dict, &msg->id, msg);

    if (!string_empty(&pool->hash_tag)) {
        struct string *tag = &pool->hash_tag;
        uint8_t *tag_start, *tag_end;

        tag_start = dn_strchr(msg->key_start, msg->key_end, tag->data[0]);
        if (tag_start != NULL) {
            tag_end = dn_strchr(tag_start + 1, msg->key_end, tag->data[1]);
            if (tag_end != NULL) {
                key = tag_start + 1;
                keylen = (uint32_t)(tag_end - key);
            }
        }
    }

    if (keylen == 0) {
        key = msg->key_start;
        keylen = (uint32_t)(msg->key_end - msg->key_start);
    }

    ASSERT(msg->dmsg != NULL);
    if (msg->dmsg->type == DMSG_REQ) {
       local_req_forward(ctx, conn, msg, key, keylen);
    } else if (msg->dmsg->type == DMSG_REQ_FORWARD) {
        struct mbuf *orig_mbuf = STAILQ_FIRST(&msg->mhdr);
        struct datacenter *dc = server_get_dc(pool, &pool->dc);
        uint32_t rack_cnt = array_n(&dc->racks);
        uint32_t rack_index;
        for(rack_index = 0; rack_index < rack_cnt; rack_index++) {
            struct rack *rack = array_get(&dc->racks, rack_index);
            //log_debug(LOG_DEBUG, "forwarding to rack  '%.*s'",
            //            rack->name->len, rack->name->data);
            struct msg *rack_msg;
            if (string_compare(rack->name, &pool->rack) == 0 ) {
                rack_msg = msg;
            } else {
                rack_msg = msg_get(conn, msg->request, __FUNCTION__);
                if (rack_msg == NULL) {
                    log_debug(LOG_VERB, "whelp, looks like yer screwed now, buddy. no inter-rack messages for you!");
                    continue;
                }

                if (msg_clone(msg, orig_mbuf, rack_msg) != DN_OK) {
                    msg_put(rack_msg);
                    continue;
                }
                rack_msg->swallow = true;
            }

            if (log_loggable(LOG_DEBUG)) {
               log_debug(LOG_DEBUG, "forwarding request from conn '%s' to rack '%.*s' dc '%.*s' ",
                           dn_unresolve_peer_desc(conn->sd), rack->name->len, rack->name->data, rack->dc->len, rack->dc->data);
            }

            remote_req_forward(ctx, conn, rack_msg, rack, key, keylen);
        }
    }
}
Ejemplo n.º 9
0
static void
req_forward(struct context *ctx, struct conn *c_conn, struct msg *msg)
{
	struct server_pool *pool = c_conn->owner;
	uint8_t *key;
	uint32_t keylen;

	ASSERT(c_conn->client && !c_conn->proxy);

	if (msg->is_read)
		stats_pool_incr(ctx, pool, client_read_requests);
	else
		stats_pool_incr(ctx, pool, client_write_requests);

	key = NULL;
	keylen = 0;

	if (!string_empty(&pool->hash_tag)) {
		struct string *tag = &pool->hash_tag;
		uint8_t *tag_start, *tag_end;

		tag_start = dn_strchr(msg->key_start, msg->key_end, tag->data[0]);
		if (tag_start != NULL) {
			tag_end = dn_strchr(tag_start + 1, msg->key_end, tag->data[1]);
			if (tag_end != NULL) {
				key = tag_start + 1;
				keylen = (uint32_t)(tag_end - key);
			}
		}
	}

	if (keylen == 0) {
		key = msg->key_start;
		keylen = (uint32_t)(msg->key_end - msg->key_start);
	}

	// need to capture the initial mbuf location as once we add in the dynomite headers (as mbufs to the src msg),
	// that will bork the request sent to secondary racks
	struct mbuf *orig_mbuf = STAILQ_FIRST(&msg->mhdr);

	if (request_send_to_all_racks(msg)) {
		uint32_t dc_cnt = array_n(&pool->datacenters);
		uint32_t dc_index;
		for(dc_index = 0; dc_index < dc_cnt; dc_index++) {
			struct datacenter *dc = array_get(&pool->datacenters, dc_index);
			if (dc == NULL) {
				log_error("Wow, this is very bad, dc is NULL");
				return;
			}

			if (string_compare(dc->name, &pool->dc) == 0) { //send to all local racks
				//log_debug(LOG_DEBUG, "dc name  '%.*s'", dc->name->len, dc->name->data);
				uint32_t rack_cnt = array_n(&dc->racks);
				uint32_t rack_index;
				for(rack_index = 0; rack_index < rack_cnt; rack_index++) {
					struct rack *rack = array_get(&dc->racks, rack_index);
					//log_debug(LOG_DEBUG, "rack name '%.*s'", rack->name->len, rack->name->data);
					struct msg *rack_msg;
					if (string_compare(rack->name, &pool->rack) == 0 ) {
						rack_msg = msg;
					} else {
						rack_msg = msg_get(c_conn, msg->request, msg->redis);
						if (rack_msg == NULL) {
							log_debug(LOG_VERB, "whelp, looks like yer screwed now, buddy. no inter-rack messages for you!");
							continue;
						}

						msg_clone(msg, orig_mbuf, rack_msg);
						rack_msg->noreply = true;
					}

					log_debug(LOG_DEBUG, "forwarding request to conn '%s' on rack '%.*s'",
							dn_unresolve_peer_desc(c_conn->sd), rack->name->len, rack->name->data);

					remote_req_forward(ctx, c_conn, rack_msg, rack, key, keylen);
				}
			} else {
            uint32_t rack_cnt = array_n(&dc->racks);
				if (rack_cnt == 0)
					continue;

				uint32_t ran_index = rand() % rack_cnt;
				struct rack *rack = array_get(&dc->racks, ran_index);

				struct msg *rack_msg = msg_get(c_conn, msg->request, msg->redis);
				if (rack_msg == NULL) {
					log_debug(LOG_VERB, "whelp, looks like yer screwed now, buddy. no inter-rack messages for you!");
					continue;
				}

				msg_clone(msg, orig_mbuf, rack_msg);
				rack_msg->noreply = true;

				log_debug(LOG_DEBUG, "forwarding request to conn '%s' on rack '%.*s'",
						dn_unresolve_peer_desc(c_conn->sd), rack->name->len, rack->name->data);

				remote_req_forward(ctx, c_conn, rack_msg, rack, key, keylen);
			}
		}
	} else { //for read only requests
		struct rack * rack = server_get_rack_by_dc_rack(pool, &pool->rack, &pool->dc);
		remote_req_forward(ctx, c_conn, msg, rack, key, keylen);
	}
}