Esempio n. 1
0
static bool 
dyn_parse_core(struct msg *r)
{
   struct dmsg *dmsg;
   struct mbuf *b;
   uint8_t *p, *token;
   uint8_t ch = ' ';
   uint64_t num = 0;

   dyn_state = r->dyn_state;
   if (log_loggable(LOG_DEBUG)) {
      log_debug(LOG_DEBUG, "dyn_state:  %d", r->dyn_state);
   }

   if (r->dyn_state == DYN_DONE || r->dyn_state == DYN_POST_DONE)
       return true;

   b = STAILQ_LAST(&r->mhdr, mbuf, next);

   dmsg = r->dmsg;
   if (dmsg == NULL) {
      r->dmsg = dmsg_get();
      dmsg = r->dmsg;
      dmsg->owner = r;
      if (dmsg == NULL) {//should track this as a dropped message
         loga("unable to create a new dmsg");
         goto error; //should count as OOM error
      }
   }

   token = NULL;

   for (p = r->pos; p < b->last; p++) {
      ch = *p;
      switch (dyn_state) {
      case DYN_START:
         if (log_loggable(LOG_DEBUG)) {
            log_debug(LOG_DEBUG, "DYN_START");
         }
         if (ch != ' ' && ch != '$') {
            break;
         }

         if (ch == ' ') {
            if (token == NULL)
               token = p;

            break;
         }

         if (ch == '$') {
              if (p + 5 < b->last) {
                  if ((*(p+1) == '2') &&
                      (*(p+2) == '0') &&
                      (*(p+3) == '1') &&
                      (*(p+4) == '4') &&
                      (*(p+5) == '$')) {
                     dyn_state = DYN_MAGIC_STRING;
                     p += 5;
                  } else {
                     //goto skip;
                     token = NULL; //reset
                  }
              } else {
                    goto split;
              }
         } else {
            loga("Facing a weird char %c", p);
            //goto skip;
            token = NULL; //reset
         }

         break;

      case DYN_MAGIC_STRING:
         if (log_loggable(LOG_DEBUG)) {
            log_debug(LOG_DEBUG, "DYN_MAGIC_STRING");
         }
         if (ch == ' ') {
            dyn_state = DYN_MSG_ID;
            num = 0;
            break;
         } else {
            //loga("char is '%c %c %c %c'", *(p-2), *(p-1), ch, *(p+1));
            token = NULL;
            loga("Facing a weird char %c", p);
            //goto skip;
            dyn_state = DYN_START;
         }

         break;

      case DYN_MSG_ID:
         if (log_loggable(LOG_DEBUG)) {
            log_debug(LOG_DEBUG, "DYN_MSG_ID");
            log_debug(LOG_DEBUG, "num = %d", num);
         }
         if (isdigit(ch))  {
            num = num*10 + (ch - '0');
         } else if (ch == ' ' && isdigit(*(p-1)))  {
            if (log_loggable(LOG_DEBUG)) {
               log_debug(LOG_DEBUG, "MSG ID : %d", num);
            }
            dmsg->id = num;
            dyn_state = DYN_TYPE_ID;
            num = 0;
         } else {
            //loga("char is '%c %c %c %c'", *(p-2), *(p-1), ch, *(p+1));
            //goto skip;
            token = NULL; //reset
            dyn_state = DYN_START;
            if (ch == '$')
               p -= 1;
         }
         break;

      case DYN_TYPE_ID:
         if (log_loggable(LOG_DEBUG)) {
            log_debug(LOG_DEBUG, "DYN_TYPE_ID: num = %d", num);
         }
         if (isdigit(ch))  {
            num = num*10 + (ch - '0');
         } else if (ch == ' ' && isdigit(*(p-1)))  {
            if (log_loggable(LOG_DEBUG)) {
               log_debug(LOG_DEBUG, "Type Id: %d", num);
            }
            dmsg->type = num;
            dyn_state = DYN_BIT_FIELD;
            num = 0;
         } else {
            //loga("char is '%c %c %c %c'", *(p-2), *(p-1), ch, *(p+1));
            token = NULL;
            dyn_state = DYN_START;
            if (ch == '$')
               p -= 1;
         }

         break;

      case DYN_BIT_FIELD:
         if (log_loggable(LOG_DEBUG)) {
            log_debug(LOG_DEBUG, "DYN_BIT_FIELD, num = %d", num);
         }
         if (isdigit(ch))  {
            num = num*10 + (ch - '0');
         } else if (ch == ' ' && isdigit(*(p-1)))  {
            if (log_loggable(LOG_DEBUG)) {
               log_debug(LOG_DEBUG, "DYN_BIT_FIELD : %d", num);
            }
            dmsg->bit_field = num & 0xF;
            dyn_state = DYN_VERSION;
            num = 0;
         } else {
            token = NULL;
            //loga("char is '%c %c %c %c'", *(p-2), *(p-1), ch, *(p+1));
            dyn_state = DYN_START;
            if (ch == '$')
               p -= 1;
         }

         break;

      case DYN_VERSION:
         if (log_loggable(LOG_DEBUG)) {
            log_debug(LOG_DEBUG, "DYN_VERSION: num = %d", num);
         }
         if (isdigit(ch))  {
            num = num*10 + (ch - '0');
         } else if (ch == ' ' && isdigit(*(p-1)))  {
            if (log_loggable(LOG_DEBUG)) {
               log_debug(LOG_DEBUG, "VERSION : %d", num);
            }
            dmsg->version = num;
            dyn_state = DYN_SAME_DC;
            num = 0;
         } else {
            token = NULL;
            //loga("char is '%c %c %c %c'", *(p-2), *(p-1), ch, *(p+1));
            dyn_state = DYN_START;
            if (ch == '$')
               p -= 1;
         }

         break;

      case DYN_SAME_DC:
      	if (isdigit(ch)) {
      		dmsg->same_dc = ch - '0';
      		if (log_loggable(LOG_DEBUG)) {
           	   log_debug(LOG_DEBUG, "DYN_SAME_DC %d", dmsg->same_dc);
      		}
      	} else if (ch == ' ' && isdigit(*(p-1))) {
      		dyn_state = DYN_DATA_LEN;
      		num = 0;
      	} else {
      		token = NULL;
      		//loga("char is '%c %c %c %c'", *(p-2), *(p-1), ch, *(p+1));
      		dyn_state = DYN_START;
      		if (ch == '$')
      		   p -= 1;
      	}

      	break;

      case DYN_DATA_LEN:
         if (log_loggable(LOG_DEBUG)) {
            log_debug(LOG_DEBUG, "DYN_DATA_LEN: num = %d", num);
         }
         if (ch == '*') {
            break;
         } else if (isdigit(ch))  {
            num = num*10 + (ch - '0');
         } else if (ch == ' ' && isdigit(*(p-1)))  {
            if (log_loggable(LOG_DEBUG)) {
               log_debug(LOG_DEBUG, "Data len: %d", num);
            }
            dmsg->mlen = num;
            dyn_state = DYN_DATA;
            num = 0;
         } else {
            token = NULL;
            //loga("char is '%c %c %c %c'", *(p-2), *(p-1), ch, *(p+1));
            dyn_state = DYN_START;
            if (ch == '$')
               p -= 1;
         }
         break;

      case DYN_DATA:
         if (log_loggable(LOG_DEBUG)) {
            log_debug(LOG_DEBUG, "DYN_DATA");
         }
         if (p + dmsg->mlen < b->last) {
            dmsg->data = p;
            p += dmsg->mlen - 1;
            dyn_state = DYN_SPACES_BEFORE_PAYLOAD_LEN;
         } else {
            //loga("char is '%c %c %c %c'", *(p-2), *(p-1), ch, *(p+1));
            goto split;
         }

         break;

      case DYN_SPACES_BEFORE_PAYLOAD_LEN:
         if (log_loggable(LOG_DEBUG)) {
            log_debug(LOG_DEBUG, "DYN_SPACES_BEFORE_PAYLOAD_LEN");
         }
         if (ch == ' ') {
            break;
         } else if (ch == '*') {
            dyn_state = DYN_PAYLOAD_LEN;
            num = 0;
         }

         break;

      case DYN_PAYLOAD_LEN:

         if (isdigit(ch))  {
            num = num*10 + (ch - '0');
         } else if (ch == CR)  {
            if (log_loggable(LOG_DEBUG)) {
               log_debug(LOG_DEBUG, "Payload len: %d", num);
            }
            dmsg->plen = num;
            num = 0;
            dyn_state = DYN_CRLF_BEFORE_DONE;
         } else {
            token = NULL;
            dyn_state = DYN_START;
            if (ch == '$')
               p -= 1;
         }
         break;

      case DYN_CRLF_BEFORE_DONE:
         if (log_loggable(LOG_DEBUG)) {
            log_debug(LOG_DEBUG, "DYN_CRLF_BEFORE_DONE");
         }
         if (*p == LF) {
            dyn_state = DYN_DONE;
         } else {
            token = NULL;
            dyn_state = DYN_START;
            if (ch == '$')
               p -= 1;
         }

         break;

      case DYN_DONE:
         if (log_loggable(LOG_DEBUG)) {
            log_debug(LOG_DEBUG, "DYN_DONE");
         }
         r->pos = p;
         dmsg->payload = p;
         r->dyn_state = DYN_DONE;
         b->pos = p;
         goto done;
         break;

      default:
         NOT_REACHED();
         break;

      }

   }

   if (log_loggable(LOG_DEBUG)) {
      log_debug(LOG_DEBUG, "Not fully parsed yet!!!!!!");
   }
   split:
   //this is an attempt recovery when we got a bad message
   //we try to look for the start the next good one and throw away the bad part
   if (r->dyn_state == DYN_START) {
      r->result = MSG_PARSE_AGAIN;
       if (b->last == b->end) {
          struct mbuf *nbuf = mbuf_get();
          if (nbuf == NULL) {
             loga("Unable to obtain a new mbuf for replacement!");
             mbuf_put(b);
             nbuf = mbuf_get();
             mbuf_insert_head(&r->mhdr, nbuf);
             r->pos = nbuf->pos;
             return false;
         }

         //replacing the bad mbuf with a new and empty mbuf
         mbuf_insert(&r->mhdr, nbuf);
         mbuf_remove(&r->mhdr, b);
         mbuf_put(b);
         r->pos = nbuf->pos;
         return false;
       } else { //split it and throw away the bad portion
           struct mbuf *nbuf;

           nbuf = mbuf_split(&r->mhdr, r->pos, NULL, NULL);
          if (nbuf == NULL) {
               return DN_ENOMEM;
          }
          mbuf_insert(&r->mhdr, nbuf);
          mbuf_remove(&r->mhdr, b);
          r->pos = nbuf->pos;
          return false;
       }

   }

   if (mbuf_length(b) == 0 || b->last == b->end) {
      if (log_loggable(LOG_DEBUG)) {
          log_debug(LOG_DEBUG, "Would this case ever happen?");
      }
      r->result = MSG_PARSE_AGAIN;
      return false;
   }

   if (r->pos == b->last) {
       if (log_loggable(LOG_DEBUG)) {
           log_debug(LOG_DEBUG, "Forward to reading the new block of data");
       }
       r->dyn_state = DYN_START;
       r->result = MSG_PARSE_AGAIN;
       token = NULL;
       return false;
   }

   if (log_loggable(LOG_VVERB)) {
      log_debug(LOG_VVERB, "in split");
   }
   r->dyn_state = DYN_START;
   r->pos = token;
   r->result = MSG_PARSE_REPAIR;
   if (log_loggable(LOG_VVERB)) {
      log_hexdump(LOG_VVERB, b->pos, mbuf_length(b), "split and inspecting req %"PRIu64" "
            "res %d type %d state %d", r->id, r->result, r->type,
            r->dyn_state);

      log_hexdump(LOG_VVERB, b->start, b->last - b->start, "split and inspecting full req %"PRIu64" "
            "res %d type %d state %d", r->id, r->result, r->type,
            r->dyn_state);
   }
   return false;

   done:
   r->pos = p;
   dmsg->source_address = r->owner->addr;

   if (log_loggable(LOG_VVERB)) {
      log_debug(LOG_VVERB, "at done with p at %d", p);
      log_hexdump(LOG_VVERB, r->pos, b->last - r->pos, "done and inspecting req %"PRIu64" "
            "res %d type %d state %d", r->id, r->result, r->type,
            r->dyn_state);
      log_hexdump(LOG_VVERB, b->start, b->last - b->start, "inspecting req %"PRIu64" "
            "res %d type %d state %d", r->id, r->result, r->type,
            r->dyn_state);
   }

   return true;

   error:
   log_debug(LOG_ERR, "at error for state %d and c %c", dyn_state, *p);
   r->result = MSG_PARSE_ERROR;
   r->pos = p;
   errno = EINVAL;

   if (log_loggable(LOG_ERR)) {
      log_hexdump(LOG_ERR, b->pos, mbuf_length(b), "parsed bad req %"PRIu64" "
            "res %d type %d state %d", r->id, r->result, r->type,
            dyn_state);
      log_hexdump(LOG_ERR, p, b->last - p, "inspecting req %"PRIu64" "
            "res %d type %d state %d", r->id, r->result, r->type,
            dyn_state);
   }
   r->dyn_state = dyn_state;

   return false;
}
Esempio n. 2
0
/* There are chances that the request to the remote peer or its response got dropped.
 * Hence we may not always receive a response to the request at the head of the FIFO.
 * Hence what we do is we mark that request as errored and move on the next one
 * in the outgoing queue. This works since we always have message ids in monotonically
 * increasing order.
 */
static void
dnode_rsp_forward(struct context *ctx, struct conn *peer_conn, struct msg *rsp)
{
    rstatus_t status;
    struct msg *req;
    struct conn *c_conn;

    ASSERT(!peer_conn->dnode_client && !peer_conn->dnode_server);

    /* response from a peer implies that peer is ok and heartbeating */
    dnode_peer_ok(ctx, peer_conn);

    /* dequeue peer message (request) from peer conn */
    while (true) {
        req = TAILQ_FIRST(&peer_conn->omsg_q);
        log_debug(LOG_VERB, "dnode_rsp_forward entering req %p rsp %p...", req, rsp);
        c_conn = req->owner;
        if (req->id == rsp->dmsg->id) {
            dnode_rsp_forward_match(ctx, peer_conn, rsp);
            return;
        }
        // Report a mismatch and try to rectify
        log_error("MISMATCH: dnode %c %d rsp_dmsg_id %u req %u:%u dnode rsp %u:%u",
                  peer_conn->dnode_client ? 'c' : (peer_conn->dnode_server ? 's' : 'p'),
                  peer_conn->sd, rsp->dmsg->id, req->id, req->parent_id, rsp->id,
                  rsp->parent_id);
        if (c_conn && conn_to_ctx(c_conn))
            stats_pool_incr(conn_to_ctx(c_conn), c_conn->owner,
                            peer_mismatch_requests);

        // TODO : should you be worried about message id getting wrapped around to 0?
        if (rsp->dmsg->id < req->id) {
            // We received a response from the past. This indeed proves out of order
            // responses. A blunder to the architecture. Log it and drop the response.
            log_error("MISMATCH: received response from the past. Dropping it");
            dnode_rsp_put(rsp);
            return;
        }

        if (req->consistency == DC_ONE) {
            if (req->swallow) {
                // swallow the request and move on the next one
                dnode_rsp_swallow(ctx, peer_conn, req, NULL);
                continue;
            }
            log_warn("req %d:%d with DC_ONE consistency is not being swallowed");
        }

        if ((req->consistency == DC_QUORUM) && !peer_conn->same_dc) {
            if (req->swallow) {
                // swallow the request and move on the next one
                dnode_rsp_swallow(ctx, peer_conn, req, NULL);
                continue;
            }
            log_warn("req %d:%d with DC_QUORUM consistency is not being swallowed");
        }

        log_error("MISMATCHED DNODE RSP RECEIVED %c %d dmsg->id %u req %u:%u rsp %u:%u, skipping....",
                  peer_conn->dnode_client ? 'c' : (peer_conn->dnode_server ? 's' : 'p'),
                  peer_conn->sd, rsp->dmsg->id,
                  req->id, req->parent_id, rsp->id, rsp->parent_id);
        ASSERT(req != NULL && req->peer == NULL);
        ASSERT(req->request && !req->done);

        if (log_loggable(LOG_VVERB)) {
            loga("skipping req:   ");
            msg_dump(req);
        }


        peer_conn->dequeue_outq(ctx, peer_conn, req);
        req->done = 1;

        // Create an appropriate response for the request so its propagated up;
        struct msg *err_rsp = msg_get(peer_conn, false, peer_conn->data_store);
        err_rsp->error = req->error = 1;
        err_rsp->err = req->err = BAD_FORMAT;
        err_rsp->dyn_error = req->dyn_error = BAD_FORMAT;
        err_rsp->dmsg = dmsg_get();
        err_rsp->dmsg->id = req->id;
        log_debug(LOG_VERB, "%p <-> %p", req, err_rsp);
        /* establish err_rsp <-> req (response <-> request) link */
        req->peer = err_rsp;
        err_rsp->peer = req;

        log_error("Peer connection s %d skipping request %u:%u, dummy err_rsp %u:%u",
                  peer_conn->sd, req->id, req->parent_id, err_rsp->id, err_rsp->parent_id);
        rstatus_t status =
            conn_handle_response(c_conn, req->parent_id ? req->parent_id : req->id,
                                 err_rsp);
        IGNORE_RET_VAL(status);
        if (req->swallow) {
            log_debug(LOG_INFO, "swallow request %d:%d", req->id, req->parent_id);
            req_put(req);
        }
    }
}
Esempio n. 3
0
static bool 
dyn_parse_core(struct msg *r)
{
	struct dmsg *dmsg;
	struct mbuf *b;
	uint8_t *p;
	uint8_t ch;
	uint64_t num = 0;

	state = r->dyn_state;
	b = STAILQ_LAST(&r->mhdr, mbuf, next);

	dmsg = r->dmsg;
	if (dmsg == NULL) {
		r->dmsg = dmsg_get();
		dmsg = r->dmsg;
		if (dmsg == NULL) {//should track this as a dropped message
			goto error; //should count as OOM error
		}
	}

	//log_hexdump(LOG_VERB, b->pos, mbuf_length(b), "dyn parser: parsed req %"PRIu64" res %d type %d", r->id, r->result, r->type, r->dyn_state);

	for (p = r->pos; p < b->last; p++) {
		ch = *p;
		switch (state) {
		case DYN_START:
			//log_debug(LOG_DEBUG, "DYN_START");
			if (ch == ' ') {
				break;
			} else if (isdigit(ch)) {
				num = ch - '0';
				state = DYN_MAGIC_NUMBER;
			} else {
				goto skip;
			}

			break;

		case DYN_MAGIC_NUMBER:
			//log_debug(LOG_DEBUG, "DYN_MAGIC_NUMBER");
			//log_debug(LOG_DEBUG, "num = %d", num);
			if (isdigit(ch))  {
				num = num*10 + (ch - '0');
			} else {
				if (num == MAGIC_NUMBER) {
					state = DYN_SPACES_BEFORE_MSG_ID;
				} else {
					goto error;
				}
			}

			break;

		case DYN_SPACES_BEFORE_MSG_ID:
			//log_debug(LOG_DEBUG, "DYN_SPACES_BEFORE_MSG_ID");
			if (ch == ' ') {
				break;
			} else if (isdigit(ch)) {
				num = ch - '0';
				state = DYN_MSG_ID;
			}  else {
				goto error;
			}

			break;

		case DYN_MSG_ID:
			log_debug(LOG_DEBUG, "DYN_MSG_ID");
			log_debug(LOG_DEBUG, "num = %d", num);
			if (isdigit(ch))  {
				num = num*10 + (ch - '0');
			} else if (ch != ' ') {
				goto error;
			} else {

				//if (num >= 0) {
				//log_debug(LOG_DEBUG, "MSG ID : %d", num);
				dmsg->id = num;
				state = DYN_SPACES_BEFORE_TYPE_ID;
				//} else {
					//   goto error;
				//}
			}
			break;

		case DYN_SPACES_BEFORE_TYPE_ID:
			log_debug(LOG_DEBUG, "DYN_SPACES_BEFORE_TYPE_ID");
			if (ch == ' ') {
				break;
			} else if (isdigit(ch)) {
				num = ch - '0';
				state = DYN_TYPE_ID;
			}  else {
				goto error;
			}

			break;

		case DYN_TYPE_ID:
			log_debug(LOG_DEBUG, "DYN_TYPE_ID");
			log_debug(LOG_DEBUG, "num = %d", num);
			if (isdigit(ch))  {
				num = num*10 + (ch - '0');
			} else {
				if (num > 0)  {
					log_debug(LOG_DEBUG, "Type Id: %d", num);
					dmsg->type = num;
					//state = DYN_SPACES_BEFORE_VERSION;
					state = DYN_SPACES_BEFORE_BIT_FIELD;
				} else {
					goto error;
				}
			}

			break;

		case DYN_SPACES_BEFORE_BIT_FIELD:
			if (ch == ' ') {
				break;
			} else if (isdigit(ch)) {
				num = ch - '0';
				state = DYN_BIT_FIELD;
			} else {
				goto error;
			}
			break;

		case DYN_BIT_FIELD:
			log_debug(LOG_DEBUG, "DYN_BIT_FIELD");
			log_debug(LOG_DEBUG, "num = %d", num);
			if (isdigit(ch))  {
				num = num*10 + (ch - '0');
			} else {
				if (ch == ' ')  {
					log_debug(LOG_DEBUG, "DYN_BIT_FIELD : %d", num);
					dmsg->bit_field = num & 0xF;
					state = DYN_SPACES_BEFORE_VERSION;
				} else {
					goto error;
				}
			}

			log_debug(LOG_DEBUG, "Post DYN_BIT_FIELD");
			log_debug(LOG_DEBUG, "num = %d", num);

			break;

		case DYN_SPACES_BEFORE_VERSION:
			log_debug(LOG_DEBUG, "DYN_SPACES_BEFORE_VERSION");
			if (ch == ' ') {
				break;
			} else if (isdigit(ch)) {
				num = ch - '0';
				state = DYN_VERSION;
			}  else {
				goto error;
			}

			break;

		case DYN_VERSION:
			log_debug(LOG_DEBUG, "DYN_VERSION");
			log_debug(LOG_DEBUG, "num = %d", num);
			if (isdigit(ch))  {
				num = num*10 + (ch - '0');
			} else {
				if (ch == ' ')  {
					//log_debug(LOG_DEBUG, "VERSION : %d", num);
					dmsg->version = num;
					state = DYN_SPACES_BEFORE_STAR;
				} else {
					goto error;
				}
			}

			break;

		case DYN_SPACES_BEFORE_STAR:
			//log_debug(LOG_DEBUG, "DYN_CRLF_BEFORE_STAR");
			if (ch == ' ')  {
				break;
			} else if (ch == '*') {
				state = DYN_DATA_LEN;
				num = 0;
			} else {
				goto error;
			}

			//else {
			//	state = DYN_STAR;
			//}

			break;

		//case DYN_STAR:
			//log_debug(LOG_DEBUG, "DYN_STAR");
		//	if (ch == '*') {
		//		state = DYN_DATA_LEN;
		//		num = 0;
		//	} else {
		//		goto error;
		//	}

		//	break;

		case DYN_DATA_LEN:
			log_debug(LOG_DEBUG, "DYN_DATA_LEN");
			log_debug(LOG_DEBUG, "num = %d", num);
			if (isdigit(ch))  {
				num = num*10 + (ch - '0');
			} else {
				if (ch == ' ')  {
					log_debug(LOG_DEBUG, "Data len: %d", num);
					dmsg->mlen = num;
					state = DYN_SPACE_BEFORE_DATA;
					num = 0;
				} else {
					goto error;
				}
			}
			break;

		case DYN_SPACE_BEFORE_DATA:
			log_debug(LOG_DEBUG, "DYN_SPACE_BEFORE_DATA");
			state = DYN_DATA;
			break;

		case DYN_DATA:
			log_debug(LOG_DEBUG, "DYN_DATA");
			p -= 1;
			if (dmsg->mlen > 0)  {
				dmsg->data = p;
				p += dmsg->mlen - 1;
				state = DYN_SPACES_BEFORE_PAYLOAD_LEN;
			} else {
				goto error;
			}

			break;

		case DYN_SPACES_BEFORE_PAYLOAD_LEN: //this only need in dynomite's custome msg
			log_debug(LOG_DEBUG, "DYN_SPACES_BEFORE_PAYLOAD_LEN");
			if (ch == ' ') {
				break;
			} else if (ch == '*') {
				state = DYN_PAYLOAD_LEN;
				num = 0;
			} else {
				goto error;
			}

			break;

		case DYN_PAYLOAD_LEN:
			if (isdigit(ch))  {
				num = num*10 + (ch - '0');
			} else {
				if (ch == CR)  {
					log_debug(LOG_DEBUG, "Payload len: %d", num);
					dmsg->plen = num;
					state = DYN_CRLF_BEFORE_DONE;
					num = 0;
				} else {
					goto error;
				}
			}
			break;

		case DYN_CRLF_BEFORE_DONE:
			//log_debug(LOG_DEBUG, "DYN_CRLF_BEFORE_DONE");
			if (*p == LF) {
				state = DYN_DONE;
			} else {
				goto error;
			}

			break;

		case DYN_DONE:
			//log_debug(LOG_DEBUG, "DYN_DONE");
			r->pos = p;
			dmsg->payload = p;
			r->dyn_state = DYN_DONE;
			b->pos = p;
			goto done;
			break;

		default:
			NOT_REACHED();
			break;

		}

	}

	done:

	dmsg->owner = r;
	dmsg->source_address = r->owner->addr;
    //r->mlen = mbuf_length(b);
	//log_debug(LOG_DEBUG, "at done with p at %d", p);
	dmsg_dump(r->dmsg);
	log_hexdump(LOG_VERB, b->pos, mbuf_length(b), "dyn: parsed req %"PRIu64" res %d "
			"type %d state %d rpos %d of %d", r->id, r->result, r->type,
			r->dyn_state, r->pos - b->pos, b->last - b->pos);


	return true;

	skip:
	//log_debug(LOG_DEBUG, "This is not a dyn message");
	dmsg->type = DMSG_UNKNOWN;
	dmsg->owner = r;
	dmsg->source_address = r->owner->addr;
	return true;

	error:
	log_debug(LOG_ERR, "at error");
	r->result = MSG_PARSE_ERROR;
	r->state = state;
	errno = EINVAL;

	log_hexdump(LOG_INFO, b->pos, mbuf_length(b), "parsed bad req %"PRIu64" "
			"res %d type %d state %d", r->id, r->result, r->type,
			r->state);
	return false;

	return true;    //fix me
}
Esempio n. 4
0
void
remote_req_forward(struct context *ctx, struct conn *c_conn, struct msg *msg, 
                   struct rack *rack, uint8_t *key, uint32_t keylen)
{
    ASSERT((c_conn->type == CONN_CLIENT) ||
           (c_conn->type == CONN_DNODE_PEER_CLIENT));

    struct node * peer = dnode_peer_pool_server(ctx, c_conn->owner, rack, key,
                                                keylen, msg->msg_routing);
    if (peer->is_local) {
        log_debug(LOG_VERB, "c_conn: %p forwarding %d:%d is local", c_conn,
                  msg->id, msg->parent_id);
        local_req_forward(ctx, c_conn, msg, key, keylen);
        return;
    }

    /* enqueue message (request) into client outq, if response is expected */
    if (msg->expect_datastore_reply  && !msg->swallow) {
        conn_enqueue_outq(ctx, c_conn, msg);
    }
    // now get a peer connection
    struct conn *p_conn = dnode_peer_pool_server_conn(ctx, peer);
    if ((p_conn == NULL) || (p_conn->connecting)) {
        if (p_conn) {
            usec_t now = dn_usec_now();
            static usec_t next_log = 0; // Log every 1 sec
            if (now > next_log) {
                log_warn("still connecting to peer '%.*s'......",
                         peer->endpoint.pname.len, peer->endpoint.pname.data);
                next_log = now + 1000 * 1000;
            }
        }
        // No response for DC_ONE & swallow
        if ((msg->consistency == DC_ONE) && (msg->swallow)) {
            msg_put(msg);
            return;
        }
        // No response for remote dc
        struct server_pool *pool = c_conn->owner;
        bool same_dc = is_same_dc(pool, peer)? 1 : 0;
        if (!same_dc) {
            msg_put(msg);
            return;
        }
        // All other cases return a response
        struct msg *rsp = msg_get(c_conn, false, __FUNCTION__);
        msg->done = 1;
        rsp->error = msg->error = 1;
        rsp->err = msg->err = (p_conn ? PEER_HOST_NOT_CONNECTED : PEER_HOST_DOWN);
        rsp->dyn_error = msg->dyn_error = (p_conn ? PEER_HOST_NOT_CONNECTED:
                                                    PEER_HOST_DOWN);
        rsp->dmsg = dmsg_get();
        rsp->peer = msg;
        rsp->dmsg->id =  msg->id;
        log_info("%lu:%lu <-> %lu:%lu Short circuit....", msg->id, msg->parent_id, rsp->id, rsp->parent_id);
        conn_handle_response(c_conn, msg->parent_id ? msg->parent_id : msg->id,
                             rsp);
        if (msg->swallow)
            msg_put(msg);
        return;
    }

    log_debug(LOG_VERB, "c_conn: %p forwarding %d:%d to p_conn %p", c_conn,
            msg->id, msg->parent_id, p_conn);
    dnode_peer_req_forward(ctx, c_conn, p_conn, msg, rack, key, keylen);
}