예제 #1
0
static void
ngx_http_groonga_context_receive_handler_typed(grn_ctx *context,
                                               int flags,
                                               ngx_http_groonga_handler_data_t *data)
{
  char *result = NULL;
  unsigned int result_size = 0;
  int recv_flags;

  if (!(flags & GRN_CTX_TAIL)) {
    return;
  }

  grn_ctx_recv(context, &result, &result_size, &recv_flags);

#ifdef NGX_GRN_SUPPORT_STOP_BY_COMMAND
  if (recv_flags == GRN_CTX_QUIT) {
    ngx_int_t ngx_rc;
    ngx_int_t ngx_pid;

    if (ngx_process == NGX_PROCESS_SINGLE) {
      ngx_pid = getpid();
    } else {
      ngx_pid = getppid();
    }

    ngx_rc = ngx_os_signal_process((ngx_cycle_t *)ngx_cycle,
                                   "quit",
                                   ngx_pid);
    if (ngx_rc == NGX_OK) {
      context->stat &= ~GRN_CTX_QUIT;
      grn_ctx_recv(context, &result, &result_size, &recv_flags);
      context->stat |= GRN_CTX_QUIT;
    } else {
      context->rc = GRN_OPERATION_NOT_PERMITTED;
      GRN_TEXT_PUTS(context, &(data->typed.body), "false");
      context->stat &= ~GRN_CTX_QUIT;
    }
  }
#endif

  if (result_size > 0 ||
      GRN_TEXT_LEN(&(data->typed.body)) > 0 ||
      context->rc != GRN_SUCCESS) {
    if (result_size > 0) {
      GRN_TEXT_PUT(context, &(data->typed.body), result, result_size);
    }

    grn_output_envelope(context,
                        context->rc,
                        &(data->typed.head),
                        &(data->typed.body),
                        &(data->typed.foot),
                        NULL,
                        0);
  }
}
예제 #2
0
static int
suggest_result(struct evbuffer *res_buf, const char *types, const char *query,
               const char *target_name, int threshold, int limit,
               grn_obj *cmd_buf, grn_ctx *ctx)
{
  if (target_name && types && query) {
    GRN_BULK_REWIND(cmd_buf);
    GRN_TEXT_PUTS(ctx, cmd_buf, "/d/suggest?table=item_");
    grn_text_urlenc(ctx, cmd_buf, target_name, strlen(target_name));
    GRN_TEXT_PUTS(ctx, cmd_buf, "&column=kana&types=");
    grn_text_urlenc(ctx, cmd_buf, types, strlen(types));
    GRN_TEXT_PUTS(ctx, cmd_buf, "&query=");
    grn_text_urlenc(ctx, cmd_buf, query, strlen(query));
    GRN_TEXT_PUTS(ctx, cmd_buf, "&threshold=");
    grn_text_itoa(ctx, cmd_buf, threshold);
    GRN_TEXT_PUTS(ctx, cmd_buf, "&limit=");
    grn_text_itoa(ctx, cmd_buf, limit);
    {
      char *res;
      int flags;
      unsigned int res_len;

      grn_ctx_send(ctx, GRN_TEXT_VALUE(cmd_buf), GRN_TEXT_LEN(cmd_buf), 0);
      grn_ctx_recv(ctx, &res, &res_len, &flags);

      evbuffer_add(res_buf, res, res_len);
      return res_len;
    }
  } else {
    evbuffer_add(res_buf, "{}", 2);
    return 2;
  }
}
예제 #3
0
const gchar *
grn_test_send_command(grn_ctx *context, const gchar *command)
{
  unsigned int send_id, receive_id;
  GString *result;
  const gchar **lines;

  result = g_string_new(NULL);
  lines = cut_take_string_array(g_strsplit(command, "\n", 0));
  for (; *lines; lines++) {
    gchar *command_result;
    unsigned int command_result_length;
    int flags = 0;

    send_id = grn_ctx_send(context, *lines, strlen(*lines), 0);
    receive_id = grn_ctx_recv(context, &command_result, &command_result_length,
                              &flags);
    cut_assert_equal_uint(send_id, receive_id);
    g_string_append_len(result, command_result, command_result_length);
    grn_test_assert_context(context,
                            cut_message("<%s>:<%s>", command, result->str));
  }

  return cut_take_strdup(g_string_free(result, FALSE));
}
예제 #4
0
static void
run_command(grn_ctx *context, const gchar *command)
{
  gchar *response;
  unsigned int response_length;
  int flags;

  grn_ctx_send(context, command, strlen(command), 0);
  grn_ctx_recv(context, &response, &response_length, &flags);
}
예제 #5
0
MRN_API char *mroonga_command(UDF_INIT *initid, UDF_ARGS *args, char *result,
                              unsigned long *length, char *is_null, char *error)
{
  CommandInfo *info = (CommandInfo *)initid->ptr;
  grn_ctx *ctx = &(info->ctx);
  char *command;
  unsigned int command_length;
  int flags = 0;

  if (!args->args[0]) {
    *is_null = 1;
    return NULL;
  }

  *is_null = 0;
  command = args->args[0];
  command_length = args->lengths[0];

  grn_ctx_send(ctx, command, command_length, 0);
  if (ctx->rc) {
    my_message(ER_ERROR_ON_WRITE, ctx->errbuf, MYF(0));
    goto error;
  }

  info->result.length(0);
  do {
    char *buffer;
    unsigned int buffer_length;
    grn_ctx_recv(ctx, &buffer, &buffer_length, &flags);
    if (ctx->rc) {
      my_message(ER_ERROR_ON_READ, ctx->errbuf, MYF(0));
      goto error;
    }
    if (buffer_length > 0) {
      if (info->result.reserve(buffer_length)) {
        my_error(ER_OUT_OF_RESOURCES, MYF(0), HA_ERR_OUT_OF_MEM);
        goto error;
      }
      info->result.q_append(buffer, buffer_length);
    }
  } while (flags & GRN_CTX_MORE);

  *length = info->result.length();
  return (char *)(info->result.ptr());

error:
  *error = 1;
  return NULL;
}
예제 #6
0
/*
 * call-seq:
 *   context.receive -> [ID, String]
 *
 * groongaサーバからクエリ実行結果文字列を受信する。
 */
static VALUE
rb_grn_context_receive (VALUE self)
{
    grn_ctx *context;
    char *string;
    unsigned string_size;
    int flags = 0;
    unsigned int query_id;

    context = SELF(self);
    query_id = grn_ctx_recv(context, &string, &string_size, &flags);
    rb_grn_context_check(context, self);

    return rb_ary_new3(2, UINT2NUM(query_id), rb_str_new(string, string_size));
}
예제 #7
0
static void
load_from_learner(msgpack_object *o, grn_ctx *ctx, grn_obj *cmd_buf)
{
  if (o->type == MSGPACK_OBJECT_MAP && o->via.map.size) {
    msgpack_object_kv *kv;
    kv = &(o->via.map.ptr[0]);
    if (kv->key.type == MSGPACK_OBJECT_RAW && kv->key.via.raw.size == 6 &&
        !memcmp(kv->key.via.raw.ptr, CONST_STR_LEN("target"))) {
      if (kv->val.type == MSGPACK_OBJECT_RAW) {
        int i;
        GRN_BULK_REWIND(cmd_buf);
        GRN_TEXT_PUTS(ctx, cmd_buf, "load --table ");
        GRN_TEXT_PUT(ctx, cmd_buf, kv->val.via.raw.ptr, kv->val.via.raw.size);
        grn_ctx_send(ctx, GRN_TEXT_VALUE(cmd_buf), GRN_TEXT_LEN(cmd_buf), GRN_CTX_MORE);
        grn_ctx_send(ctx, CONST_STR_LEN("["), GRN_CTX_MORE);
        if (kv->val.via.raw.size > 5) {
          if (!memcmp(kv->val.via.raw.ptr, CONST_STR_LEN("item_")) ||
              !memcmp(kv->val.via.raw.ptr, CONST_STR_LEN("pair_"))) {
            char delim = '{';
            GRN_BULK_REWIND(cmd_buf);
            for (i = 1; i < o->via.map.size; i++) {
              GRN_TEXT_PUTC(ctx, cmd_buf, delim);
              kv = &(o->via.map.ptr[i]);
              msgpack2json(&(kv->key), ctx, cmd_buf);
              GRN_TEXT_PUTC(ctx, cmd_buf, ':');
              msgpack2json(&(kv->val), ctx, cmd_buf);
              delim = ',';
            }
            GRN_TEXT_PUTC(ctx, cmd_buf, '}');
            /* printf("msg: %.*s\n", GRN_TEXT_LEN(cmd_buf), GRN_TEXT_VALUE(cmd_buf)); */
            grn_ctx_send(ctx, GRN_TEXT_VALUE(cmd_buf), GRN_TEXT_LEN(cmd_buf), GRN_CTX_MORE);
          }
        }
        grn_ctx_send(ctx, CONST_STR_LEN("]"), 0);
        {
          char *res;
          int flags;
          unsigned int res_len;
          grn_ctx_recv(ctx, &res, &res_len, &flags);
        }
      }
    }
  }
}
예제 #8
0
static void
output(grn_ctx *ctx)
{
  int flags = 0;
  char *str;
  unsigned int str_len;

  do {
    grn_ctx_recv(ctx, &str, &str_len, &flags);
    if (str_len > 0 || ctx->rc) {
      if (ctx->rc) {
        printf("ERROR (%d): %s\n", ctx->rc, ctx->errbuf);
      }
      if (str_len > 0) {
        printf("%.*s\n", str_len, str);
      }
    }
  } while (flags & GRN_CTX_MORE);
}
예제 #9
0
void
grn_test_assert_send_command_error_helper (grn_ctx     *context,
                                           grn_rc       expected_rc,
                                           const gchar *expected_message,
                                           const gchar *command,
                                           const gchar *expected_rc_expression,
                                           const gchar *expected_message_expression,
                                           const gchar *command_expression)
{
  const gchar **lines;

  lines = cut_take_string_array(g_strsplit(command, "\n", 0));
  for (; *lines; lines++) {
    grn_ctx_send(context, *lines, strlen(*lines), 0);
    if (context->rc) {
      break;
    }
  }

  if (context->rc == expected_rc &&
      cut_equal_string(expected_message, context->errbuf)) {
    gchar *command_result;
    unsigned int command_result_length;
    int flags = 0;

    cut_test_pass();
    grn_ctx_recv(context, &command_result, &command_result_length, &flags);
  } else {
    cut_set_expected(cut_take_printf("<%s>(%s)",
                                     expected_message,
                                     grn_rc_to_string(expected_rc)));
    cut_set_actual(cut_take_printf("<%s>(%s)",
                                   context->errbuf,
                                   grn_rc_to_string(context->rc)));
    cut_test_fail(cut_take_printf("<send(\"%s\")>\n"
                                  "%s:%d: %s():",
                                  command_expression,
                                  context->errfile, context->errline,
                                  context->errfunc));
  }
}
예제 #10
0
static void
ngx_http_groonga_context_receive_handler_raw(grn_ctx *context,
                                             int flags,
                                             ngx_http_groonga_handler_data_t *data)
{
  char *chunk = NULL;
  unsigned int chunk_size = 0;
  int recv_flags;
  ngx_http_request_t *r;
  ngx_log_t *log;
  grn_bool is_last_chunk;

  grn_ctx_recv(context, &chunk, &chunk_size, &recv_flags);
  data->raw.processed = GRN_TRUE;

  if (data->raw.rc != NGX_OK) {
    return;
  }

  r = data->raw.r;
  log = r->connection->log;
  is_last_chunk = (flags & GRN_CTX_TAIL);

  if (!data->raw.header_sent) {
    ngx_http_groonga_handler_set_content_type(r, grn_ctx_get_mime_type(context));
    r->headers_out.status = NGX_HTTP_OK;
    if (is_last_chunk) {
      r->headers_out.content_length_n = chunk_size;
      if (chunk_size == 0) {
        r->header_only = 1;
      }
    } else {
      r->headers_out.content_length_n = -1;
    }
    data->raw.rc = ngx_http_send_header(r);
    data->raw.header_sent = GRN_TRUE;

    if (data->raw.rc != NGX_OK) {
      return;
    }
  }

  if (chunk_size > 0 || is_last_chunk) {
    ngx_chain_t *chain;

    chain = ngx_chain_get_free_buf(r->pool, &(data->raw.free_chain));
    if (!chain) {
      ngx_log_error(NGX_LOG_ERR, log, 0,
                    "http_groonga: failed to allocate memory for chunked body");
      data->raw.rc = NGX_ERROR;
      return;
    }
    if (chunk_size == 0) {
      chain->buf->pos = NULL;
      chain->buf->last = NULL;
      chain->buf->memory = 0;
    } else {
      chain->buf->pos = (u_char *)chunk;
      chain->buf->last = (u_char *)chunk + chunk_size;
      chain->buf->memory = 1;
    }
    chain->buf->tag = (ngx_buf_tag_t)&ngx_http_groonga_module;
    chain->buf->flush = 1;
    chain->buf->temporary = 0;
    chain->buf->in_file = 0;
    if (is_last_chunk) {
      chain->buf->last_buf = 1;
    } else {
      chain->buf->last_buf = 0;
    }
    chain->next = NULL;

    data->raw.rc = ngx_http_output_filter(r, chain);
    ngx_chain_update_chains(r->pool,
                            &(data->raw.free_chain),
                            &(data->raw.busy_chain),
                            &chain,
                            (ngx_buf_tag_t)&ngx_http_groonga_module);
  }
}