/* * 既存のデータベースを開く。ブロックを指定した場合はブロッ * クに開いたデータベースを渡し、ブロックを抜けるときに閉じ * る。 * * @overload new(path, options=nil) * @!macro [new] database.new.arguments * @param options [::Hash] The name and value * pairs. Omitted names are initialized as the default value. * @option options :context (Groonga::Context.default) * データベースを結びつけるコンテキスト。省略すると * {Groonga::Context.default} を利用する。 * @!macro database.new.arguments * @return [Groonga::Database] * @overload new(path, options=nil) * @!macro database.new.arguments * @yield [database] * @yieldparam [Groonga::Database] database 開いたデータベース */ static VALUE rb_grn_database_initialize (int argc, VALUE *argv, VALUE self) { grn_ctx *context; grn_obj *old_database, *database; const char *path; VALUE rb_path, options, rb_context; rb_scan_args(argc, argv, "11", &rb_path, &options); path = StringValuePtr(rb_path); rb_grn_scan_options(options, "context", &rb_context, NULL); context = rb_grn_context_ensure(&rb_context); old_database = grn_ctx_db(context); if (old_database) grn_obj_unlink(context, old_database); reset_floating_objects(rb_context); database = grn_db_open(context, path); rb_grn_object_assign(Qnil, self, rb_context, context, database); rb_grn_context_check(context, self); rb_iv_set(self, "@context", rb_context); if (!NIL_P(rb_context)) rb_iv_set(rb_context, "database", self); return Qnil; }
static void ngx_http_groonga_close_database_callback(ngx_http_groonga_loc_conf_t *location_conf, void *user_data) { ngx_http_groonga_database_callback_data_t *data = user_data; grn_ctx *context; context = &(location_conf->context); ngx_http_groonga_context_init_logger(context, location_conf, data->pool, data->log); ngx_http_groonga_context_init_query_logger(context, location_conf, data->pool, data->log); grn_cache_current_set(context, location_conf->cache); grn_obj_close(context, grn_ctx_db(context)); ngx_http_groonga_context_log_error(data->log, context); grn_cache_current_set(context, NULL); grn_cache_close(context, location_conf->cache); grn_ctx_fin(context); }
static mrb_value ctx_get_database(mrb_state *mrb, mrb_value self) { grn_ctx *ctx = (grn_ctx *)mrb->ud; return grn_mrb_value_from_grn_obj(mrb, grn_ctx_db(ctx)); }
/* * call-seq: * context.inspect -> String * * コンテキストの中身を人に見やすい文字列で返す。 */ static VALUE rb_grn_context_inspect (VALUE self) { VALUE inspected; grn_ctx *context; grn_obj *database; VALUE rb_database; context = SELF(self); inspected = rb_str_new2("#<"); rb_str_concat(inspected, rb_inspect(rb_obj_class(self))); rb_str_cat2(inspected, " "); rb_str_cat2(inspected, "encoding: <"); rb_str_concat(inspected, rb_inspect(GRNENCODING2RVAL(context->encoding))); rb_str_cat2(inspected, ">, "); rb_str_cat2(inspected, "database: <"); database = grn_ctx_db(context); rb_database = GRNDB2RVAL(context, database, RB_GRN_FALSE); rb_str_concat(inspected, rb_inspect(rb_database)); rb_str_cat2(inspected, ">"); rb_str_cat2(inspected, ">"); return inspected; }
/* * call-seq: * context.database -> Groonga::Database * * コンテキストが使うデータベースを返す。 */ static VALUE rb_grn_context_get_database (VALUE self) { grn_ctx *context; context = SELF(self); return GRNDB2RVAL(context, grn_ctx_db(context), RB_GRN_FALSE); }
static ngx_int_t ngx_http_groonga_handler_create_data(ngx_http_request_t *r, ngx_http_groonga_handler_data_t **data_return) { ngx_int_t rc; ngx_http_groonga_loc_conf_t *location_conf; ngx_http_cleanup_t *cleanup; ngx_http_groonga_handler_data_t *data; grn_ctx *context; location_conf = ngx_http_get_module_loc_conf(r, ngx_http_groonga_module); cleanup = ngx_http_cleanup_add(r, sizeof(ngx_http_groonga_handler_data_t)); cleanup->handler = ngx_http_groonga_handler_cleanup; data = cleanup->data; *data_return = data; context = &(data->context); rc = ngx_http_groonga_context_init(context, location_conf, r->pool, r->connection->log); if (rc != NGX_OK) { return rc; } data->initialized = GRN_TRUE; data->raw.processed = GRN_FALSE; data->raw.header_sent = GRN_FALSE; data->raw.r = r; data->raw.rc = NGX_OK; data->raw.free_chain = NULL; data->raw.busy_chain = NULL; GRN_TEXT_INIT(&(data->typed.head), GRN_NO_FLAGS); GRN_TEXT_INIT(&(data->typed.body), GRN_NO_FLAGS); GRN_TEXT_INIT(&(data->typed.foot), GRN_NO_FLAGS); grn_ctx_use(context, grn_ctx_db(&(location_conf->context))); rc = ngx_http_groonga_context_check_error(r->connection->log, context); if (rc != NGX_OK) { return rc; } grn_ctx_recv_handler_set(context, ngx_http_groonga_context_receive_handler, data); return NGX_OK; }
MRN_API void mroonga_command_deinit(UDF_INIT *initid) { CommandInfo *info = (CommandInfo *)initid->ptr; if (info) { grn_obj *db = grn_ctx_db(&(info->ctx)); if (db) { grn_obj_close(&(info->ctx), db); } grn_ctx_fin(&(info->ctx)); info->result.free(); my_free(info, MYF(0)); } }
MRN_API void mroonga_snippet_deinit(UDF_INIT *initid) { st_mrn_snip_info *snip_info = (st_mrn_snip_info *) initid->ptr; if (snip_info) { if (snip_info->snippet) { grn_snip_close(&snip_info->ctx, snip_info->snippet); } snip_info->result_str.free(); grn_obj_close(&snip_info->ctx, grn_ctx_db(&snip_info->ctx)); grn_ctx_fin(&snip_info->ctx); my_free(snip_info, MYF(0)); } }
static void ngx_http_groonga_close_database_callback(ngx_http_groonga_loc_conf_t *location_conf, void *user_data) { ngx_http_groonga_database_callback_data_t *data = user_data; grn_ctx *context; context = &(location_conf->context); grn_obj_close(context, grn_ctx_db(context)); ngx_http_groonga_context_log_error(data->log, context); grn_ctx_fin(context); }
void rb_grn_context_fin (grn_ctx *context) { grn_obj *database; if (context->stat == GRN_CTX_FIN) return; database = grn_ctx_db(context); debug("context:database: %p:%p\n", context, database); if (database && database->header.type == GRN_DB) { grn_obj_unlink(context, database); } grn_ctx_fin(context); }
/* * 新しくデータベースを作成する。 * _options_ にはハッシュでオプションを指定する。 * * @example * # 一時データベースを作成: * Groonga::Database.create * * # 永続データベースを作成: * Groonga::Database.create(:path => "/tmp/db.groonga") * * @overload create(options=nil) * @return [Groonga::Database] 作成されたデータベースを返す。 * @param [::Hash] options The name and value * pairs. Omitted names are initialized as the default value. * @option options :path * データベースを保存するパス。省略すると一時データベース * となる。 * @option options :context (Groonga::Context.default) * データベースを結びつけるコンテキスト。省略すると * {Groonga::Context.default} を利用する。 */ static VALUE rb_grn_database_s_create (int argc, VALUE *argv, VALUE klass) { grn_ctx *context; grn_obj *old_database, *database; grn_db_create_optarg create_args; const char *path = NULL; VALUE rb_database; VALUE rb_path, options, rb_context, builtin_type_names; grn_bool owner; rb_scan_args(argc, argv, "01", &options); rb_grn_scan_options(options, "path", &rb_path, "context", &rb_context, "builtin_type_names", &builtin_type_names, NULL); if (!NIL_P(rb_path)) path = StringValuePtr(rb_path); context = rb_grn_context_ensure(&rb_context); create_args.builtin_type_names = NULL; create_args.n_builtin_type_names = 0; old_database = grn_ctx_db(context); if (old_database) grn_obj_unlink(context, old_database); reset_floating_objects(rb_context); database = grn_db_create(context, path, &create_args); rb_grn_context_check(context, rb_ary_new_from_values(argc, argv)); owner = (context->flags & GRN_CTX_PER_DB) ? GRN_FALSE : GRN_TRUE; rb_database = GRNOBJECT2RVAL(klass, context, database, owner); rb_iv_set(rb_database, "@context", rb_context); if (!NIL_P(rb_context)) rb_iv_set(rb_context, "database", rb_database); rb_grn_context_check(context, rb_ary_new_from_values(argc, argv)); if (rb_block_given_p()) return rb_ensure(rb_yield, rb_database, rb_grn_database_close, rb_database); else return rb_database; }
static ngx_int_t ngx_http_groonga_handler_create_data(ngx_http_request_t *r, ngx_http_groonga_handler_data_t **data_return) { ngx_int_t rc; ngx_http_groonga_loc_conf_t *location_conf; ngx_http_cleanup_t *cleanup; ngx_http_groonga_handler_data_t *data; grn_ctx *context; location_conf = ngx_http_get_module_loc_conf(r, ngx_http_groonga_module); cleanup = ngx_http_cleanup_add(r, sizeof(ngx_http_groonga_handler_data_t)); cleanup->handler = ngx_http_groonga_handler_cleanup; data = cleanup->data; *data_return = data; context = &(data->context); grn_ctx_init(context, GRN_NO_FLAGS); GRN_TEXT_INIT(&(data->head), GRN_NO_FLAGS); GRN_TEXT_INIT(&(data->body), GRN_NO_FLAGS); GRN_TEXT_INIT(&(data->foot), GRN_NO_FLAGS); grn_ctx_use(context, grn_ctx_db(&(location_conf->context))); rc = ngx_http_groonga_context_check_error(r->connection->log, context); if (rc != NGX_OK) { return rc; } grn_ctx_recv_handler_set(context, ngx_http_groonga_context_receive_handler, data); return NGX_OK; }
MRN_API my_bool mroonga_command_init(UDF_INIT *initid, UDF_ARGS *args, char *message) { CommandInfo *info = NULL; initid->ptr = NULL; if (args->arg_count != 1) { sprintf(message, "mroonga_command(): Incorrect number of arguments: %u for 1", args->arg_count); goto error; } if (args->arg_type[0] != STRING_RESULT) { strcpy(message, "mroonga_command(): The 1st argument must be command as string"); goto error; } initid->maybe_null = 1; initid->const_item = 1; info = (CommandInfo *)my_malloc(sizeof(CommandInfo), MYF(MY_WME | MY_ZEROFILL)); if (!info) { strcpy(message, "mroonga_command(): out of memory"); goto error; } grn_ctx_init(&(info->ctx), 0); { const char *current_db_path = current_thd->db; const char *action; if (current_db_path) { action = "open database"; mrn::PathMapper mapper(current_db_path); grn_db_open(&(info->ctx), mapper.db_path()); } else { action = "create anonymous database"; grn_db_create(&(info->ctx), NULL, NULL); } if (info->ctx.rc != GRN_SUCCESS) { sprintf(message, "mroonga_command(): failed to %s: %s", action, info->ctx.errbuf); goto error; } } initid->ptr = (char *)info; return FALSE; error: if (info) { grn_obj *db; db = grn_ctx_db(&(info->ctx)); if (db) { grn_obj_close(&(info->ctx), db); } grn_ctx_fin(&(info->ctx)); my_free(info, MYF(0)); } return TRUE; }
grn_snip * grn_snip_open(grn_ctx *ctx, int flags, unsigned int width, unsigned int max_results, const char *defaultopentag, unsigned int defaultopentag_len, const char *defaultclosetag, unsigned int defaultclosetag_len, grn_snip_mapping *mapping) { int copy_tag; grn_snip *ret = NULL; if (!(ret = GRN_MALLOC(sizeof(grn_snip)))) { GRN_LOG(ctx, GRN_LOG_ALERT, "grn_snip allocation failed on grn_snip_open"); return NULL; } if (max_results > MAX_SNIP_RESULT_COUNT || max_results == 0) { GRN_LOG(ctx, GRN_LOG_WARNING, "max_results is invalid on grn_snip_open"); GRN_FREE(ret); return NULL; } GRN_API_ENTER; ret->encoding = ctx->encoding; ret->flags = flags; ret->width = width; ret->max_results = max_results; ret->defaultopentag = NULL; ret->defaultclosetag = NULL; copy_tag = flags & GRN_SNIP_COPY_TAG; if (grn_snip_set_default_tag(ctx, &(ret->defaultopentag), &(ret->defaultopentag_len), defaultopentag, defaultopentag_len, copy_tag)) { GRN_FREE(ret); GRN_API_RETURN(NULL); } if (grn_snip_set_default_tag(ctx, &(ret->defaultclosetag), &(ret->defaultclosetag_len), defaultclosetag, defaultclosetag_len, copy_tag)) { if (copy_tag && ret->defaultopentag) { GRN_FREE((void *)ret->defaultopentag); } GRN_FREE(ret); GRN_API_RETURN(NULL); } ret->cond_len = 0; ret->mapping = mapping; ret->nstr = NULL; ret->tag_count = 0; ret->snip_count = 0; if (ret->flags & GRN_SNIP_NORMALIZE) { ret->normalizer = GRN_NORMALIZER_AUTO; } else { ret->normalizer = NULL; } GRN_DB_OBJ_SET_TYPE(ret, GRN_SNIP); { grn_obj *db; grn_id id; db = grn_ctx_db(ctx); id = grn_obj_register(ctx, db, NULL, 0); DB_OBJ(ret)->header.domain = GRN_ID_NIL; DB_OBJ(ret)->range = GRN_ID_NIL; grn_db_obj_init(ctx, db, id, DB_OBJ(ret)); } GRN_API_RETURN(ret); }
/* * スニペットを作成する。 * * @overload new(options={}) * @param options [::Hash] The name and value * pairs. Omitted names are initialized as the default value. * @option options :context (Groonga::Context.default) * スキーマ作成時に使用するGroonga::Contextを指定する。 * @option options :normalize * キーワード文字列・スニペット元の文字列を正規化するかどうか。 * 省略した場合は +false+ で正規化しない。 * @option options :skip_leading_spaces (false) * 先頭の空白を無視するかどうか。省略した場合は +false+ で無視しない。 * @option options :width (100) * スニペット文字列の長さ。省略した場合は100文字。 * @option options :max_results (3) * 生成するスニペットの最大数。省略した場合は3。 * @option options :html_escape (false) * スニペット内の +<+ , +>+ , +&+ , +"+ をHTMLエスケープするかどうか。 * 省略した場合は +false+ で、HTMLエスケープしない。 * @option options :default_open_tag ("") * デフォルトの開始タグ。省略した場合は""(空文字列) * @option options :default_close_tag ("") * デフォルトの終了タグ。省略した場合は""(空文字列) */ static VALUE rb_grn_snippet_initialize (int argc, VALUE *argv, VALUE self) { grn_ctx *context = NULL; grn_snip *snippet = NULL; VALUE options; VALUE rb_context, rb_normalize, rb_skip_leading_spaces; VALUE rb_width, rb_max_results, rb_default_open_tag, rb_default_close_tag; VALUE rb_html_escape; int flags = GRN_SNIP_COPY_TAG; unsigned int width = 100; unsigned int max_results = 3; char *default_open_tag = NULL; unsigned int default_open_tag_length = 0; char *default_close_tag = NULL; unsigned int default_close_tag_length = 0; grn_snip_mapping *mapping = NULL; rb_scan_args(argc, argv, "01", &options); rb_grn_scan_options(options, "context", &rb_context, "normalize", &rb_normalize, "skip_leading_spaces", &rb_skip_leading_spaces, "width", &rb_width, "max_results", &rb_max_results, "default_open_tag", &rb_default_open_tag, "default_close_tag", &rb_default_close_tag, "html_escape", &rb_html_escape, NULL); context = rb_grn_context_ensure(&rb_context); if (!grn_ctx_db(context)) { rb_raise(rb_eArgError, "Groonga::Context should be associated with a database by " "Groonga::Database#open or #create: %s", rb_grn_inspect(rb_context)); } if (RVAL2CBOOL(rb_normalize)) flags |= GRN_SNIP_NORMALIZE; if (RVAL2CBOOL(rb_skip_leading_spaces)) flags |= GRN_SNIP_SKIP_LEADING_SPACES; if (!NIL_P(rb_width)) width = NUM2UINT(rb_width); if (!NIL_P(rb_max_results)) max_results = NUM2UINT(rb_max_results); if (!NIL_P(rb_default_open_tag)) { default_open_tag = StringValuePtr(rb_default_open_tag); default_open_tag_length = RSTRING_LEN(rb_default_open_tag); } if (!NIL_P(rb_default_close_tag)) { default_close_tag = StringValuePtr(rb_default_close_tag); default_close_tag_length = RSTRING_LEN(rb_default_close_tag); } if (RVAL2CBOOL(rb_html_escape)) mapping = (grn_snip_mapping *)-1; snippet = grn_snip_open(context, flags, width, max_results, default_open_tag, default_open_tag_length, default_close_tag, default_close_tag_length, mapping); rb_grn_context_check(context, rb_ary_new4(argc, argv)); rb_grn_object_assign(Qnil, self, rb_context, context, (grn_obj *)snippet); rb_grn_context_register_floating_object(DATA_PTR(self)); rb_iv_set(self, "@context", rb_context); return Qnil; }
MRN_API my_bool mroonga_snippet_init(UDF_INIT *initid, UDF_ARGS *args, char *message) { uint i; st_mrn_snip_info *snip_info = NULL; bool can_open_snippet = TRUE; initid->ptr = NULL; if (args->arg_count < 11 || (args->arg_count - 11) % 3) { sprintf(message, "Incorrect number of arguments for mroonga_snippet(): %u", args->arg_count); goto error; } if (args->arg_type[0] != STRING_RESULT) { strcpy(message, "mroonga_snippet() requires string for 1st argument"); goto error; } if (args->arg_type[1] != INT_RESULT) { strcpy(message, "mroonga_snippet() requires int for 2nd argument"); goto error; } if (args->arg_type[2] != INT_RESULT) { strcpy(message, "mroonga_snippet() requires int for 3rd argument"); goto error; } if ( args->arg_type[3] != STRING_RESULT && args->arg_type[3] != INT_RESULT ) { strcpy(message, "mroonga_snippet() requires string or int for 4th argument"); goto error; } if (args->arg_type[4] != INT_RESULT) { strcpy(message, "mroonga_snippet() requires int for 5th argument"); goto error; } if (args->arg_type[5] != INT_RESULT) { strcpy(message, "mroonga_snippet() requires int for 6th argument"); goto error; } for (i = 6; i < args->arg_count; i++) { if (args->arg_type[i] != STRING_RESULT) { sprintf(message, "mroonga_snippet() requires string for %uth argument", i); goto error; } } initid->maybe_null = 1; initid->const_item = 1; if (!(snip_info = (st_mrn_snip_info *) my_malloc(sizeof(st_mrn_snip_info), MYF(MY_WME | MY_ZEROFILL)))) { strcpy(message, "mroonga_snippet() out of memory"); goto error; } grn_ctx_init(&snip_info->ctx, 0); grn_db_create(&snip_info->ctx, NULL, 0); for (i = 1; i < args->arg_count; i++) { if (!args->args[i]) { can_open_snippet = FALSE; break; } } if (can_open_snippet) { if (mrn_snippet_prepare(snip_info, args, message, &snip_info->snippet)) { goto error; } } initid->ptr = (char *) snip_info; return FALSE; error: if (snip_info) { grn_obj_close(&snip_info->ctx, grn_ctx_db(&snip_info->ctx)); grn_ctx_fin(&snip_info->ctx); my_free(snip_info, MYF(0)); } return TRUE; }