[Groonga-commit] ranguba/rroonga at 34d01e9 [master] array: remove queue support

Back to archive index

Kouhei Sutou null+****@clear*****
Tue Jan 30 12:33:14 JST 2018


Kouhei Sutou	2018-01-30 12:33:14 +0900 (Tue, 30 Jan 2018)

  New Revision: 34d01e9780fe4eabbb175e9e2efe3624d54d9557
  https://github.com/ranguba/rroonga/commit/34d01e9780fe4eabbb175e9e2efe3624d54d9557

  Message:
    array: remove queue support

  Modified files:
    ext/groonga/rb-grn-array.c
    test/test-array.rb

  Modified: ext/groonga/rb-grn-array.c (+1 -272)
===================================================================
--- ext/groonga/rb-grn-array.c    2018-01-29 00:30:25 +0900 (60c105ce)
+++ ext/groonga/rb-grn-array.c    2018-01-30 12:33:14 +0900 (ad09537e)
@@ -1,6 +1,6 @@
 /* -*- coding: utf-8; mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /*
-  Copyright (C) 2009-2013  Kouhei Sutou <kou �� clear-code.com>
+  Copyright (C) 2009-2018  Kouhei Sutou <kou �� clear-code.com>
 
   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
@@ -192,274 +192,6 @@ rb_grn_array_add (int argc, VALUE *argv, VALUE self)
     }
 }
 
-typedef struct _YieldRecordCallbackData
-{
-    VALUE self;
-    VALUE record;
-    grn_id id;
-    int status;
-} YieldRecordCallbackData;
-
-static VALUE
-yield_record (VALUE user_data)
-{
-    YieldRecordCallbackData *data = (YieldRecordCallbackData *)user_data;
-    volatile VALUE record;
-
-    if (data->id == GRN_ID_NIL) {
-        record = Qnil;
-    } else {
-        record = rb_grn_record_new(data->self, data->id, Qnil);
-    }
-    data->record = record;
-
-    return rb_yield(record);
-}
-
-static void
-yield_record_callback (grn_ctx *ctx, grn_array *array,
-                       grn_id id, void *user_data)
-{
-    YieldRecordCallbackData *data = user_data;
-
-    data->id = id;
-    rb_protect(yield_record, (VALUE)(data), &(data->status));
-}
-
-/*
- * Pushes a record to the array. The record should be filled in the
- * given block. The pushed record can be pulled by
- * {Groonga::Array#pull}.
- *
- * @example A program that pushes a job without error handling
- *   queue = Groonga::Array.create(:name => "CrawlURLQueue")
- *   queue.define_column("url", "ShortText")
- *   urls = ["http://groonga.org/", "http://ranguba.org/"]
- *   urls.each do |url|
- *     queue.push do |record|
- *       record.url = url
- *     end
- *   end
- *
- * @example A program that pulls a job without error handling
- *   queue = Groonga::Array.open(:name => "CrawlURLQueue")
- *   loop do
- *     url = nil
- *     queue.pull do |record|
- *       url = record.url
- *       record.delete
- *     end
- *     # Crawl URL
- *   end
- *
- * The record that is passed to the given block may be nil. You need
- * to handle the case. For example, just ignoring it or reports an
- * error.
- *
- * @example A program that pushes a job with error handling
- *   queue = Groonga::Array.create(:name => "CrawlURLQueue")
- *   queue.define_column("url", "ShortText")
- *   urls = ["http://groonga.org/", "http://ranguba.org/"]
- *   urls.each do |url|
- *     queue.push do |record|
- *       record.url = url if record # check record is not nil
- *     end
- *   end
- *
- * If an error is occurred in the given block, the pushed record may
- * not be filled completely. You should handle the case in pull side.
- *
- * @example A program that has an error in push block
- *   queue = Groonga::Array.create(:name => "CrawlURLQueue")
- *   queue.define_column("url", "ShortText")
- *   urls = ["http://groonga.org/", "http://ranguba.org/"]
- *   urls.each do |url|
- *     queue.push do |record|
- *       record.url = uri # Typo! It should be ur*l* not ur*i*
- *       # record.url isn't set
- *     end
- *   end
- *
- * @example A program that pulls a job with error handling
- *   queue = Groonga::Array.open(:name => "CrawlURLQueue")
- *   loop do
- *     url = nil
- *     queue.pull do |record|
- *       url = record.url # record.url is nil!
- *       record.delete
- *     end
- *     next if url.nil? # Ignore an uncompleted added job
- *     # Crawl URL
- *   end
- *
- * @overload push
- *   @yield [record] Filles columns of a pushed record in the given block.
- *   @yieldparam record [Groonga::Record or nil]
- *     A pushed record. It is nil when pushing is failed.
- *   @return [Groonga::Record or nil] A pushed record that is yielded.
- *
- */
-static VALUE
-rb_grn_array_push (VALUE self)
-{
-    grn_ctx *context = NULL;
-    grn_obj *table;
-    YieldRecordCallbackData data;
-
-    if (!rb_block_given_p()) {
-        rb_raise(rb_eArgError,
-                 "tried to call Groonga::Array#push without a block");
-    }
-
-    table = SELF(self, &context);
-
-    data.self = self;
-    data.record = Qnil;
-    data.status = 0;
-    grn_array_push(context, (grn_array *)table, yield_record_callback, &data);
-    if (data.status != 0) {
-        rb_jump_tag(data.status);
-    }
-    rb_grn_context_check(context, self);
-
-    return data.record;
-}
-
-/*
- * Pulls a record from the array. The required values should be
- * retrieved in the given block.
- *
- * If {Groonga::Array#push} failes to fill values of the pushed
- * record, the pulled record may be uncompleted. It should be handled
- * by your application.
- *
- * If you passes @:block? => true@ option, the pull operation blocks
- * until a pushed record is pushed. It is the default behavior.
- *
- * If you passes @:block? => false@ option, the pull operation returns
- * immediately, the given block isn't called and returns nil when no
- * record exist in the array.
- *
- * @example A program that pulls with non-block mode
- *   queue = Groonga::Array.open(:name => "CrawlURLQueue")
- *   loop do
- *     url = nil
- *     # The case for no pushed records in the array.
- *     pulled_record = queue.pull(:block? => false) do |record|
- *       # This block isn't called
- *       url = record.url
- *       record.delete
- *     end
- *     p pulled_record.nil? # => true
- *   end
- *
- * Note that your signal handlers can't be ran while a pull
- * operation. You need to use {Groonga::Array#unblock} from
- * another process to unblock the pull operation. If you call
- * {Groonga::Array#unblock}, signal handler can be ran.
- *
- * @example Signal handler isn't called
- *   queue = Groonga::Array.open(:name => "CrawlURLQueue")
- *   trap(:INT) do
- *     p :not_called!
- *   end
- *   queue.pull do |record|
- *     # Send SIGINT while blocking the pull operation.
- *     # The signal handler isn't called.
- *   end
- *
- * @see Groonga::Array#push Examples exist in the push documentation.
- *
- * @overload pull(options={})
- *   @param [::Hash] options The option parameters.
- *   @option options [Boolean] :block? (true)
- *     Whether the pull operation is blocked or not when no record exist
- *     in the array.
- *   @yield [record] Gets required values for a pull record in the given block.
- *   @yieldparam record [Groonga::Record or nil]
- *     A pulled record. It is nil when no records exist in the array
- *     and @block?@ parameter is not @true �� .
- *   @return [Groonga::Record or nil] A pulled record that is yielded.
- *
- */
-static VALUE
-rb_grn_array_pull (int argc, VALUE *argv, VALUE self)
-{
-    grn_ctx *context = NULL;
-    grn_obj *table;
-    VALUE options;
-    VALUE rb_block_p;
-    YieldRecordCallbackData data;
-
-    rb_scan_args(argc, argv, "01", &options);
-
-    rb_grn_scan_options(options,
-                        "block?", &rb_block_p,
-                        NULL);
-
-    if (!rb_block_given_p()) {
-        rb_raise(rb_eArgError,
-                 "tried to call Groonga::Array#pull without a block");
-    }
-
-    table = SELF(self, &context);
-
-    if (NIL_P(rb_block_p)) {
-        rb_block_p = Qtrue;
-    }
-
-    data.self = self;
-    data.record = Qnil;
-    data.status = 0;
-    grn_array_pull(context, (grn_array *)table, RVAL2CBOOL(rb_block_p),
-                   yield_record_callback, &data);
-    if (data.status != 0) {
-        rb_jump_tag(data.status);
-    }
-    rb_grn_context_check(context, self);
-
-    return data.record;
-}
-
-/*
- * Unblocks all {Groonga::Array#pull} operations for the array.
- *
- * @example Pull, unblock and signal
- *   # pull.rb
- *   queue = Groonga::Array.open(:name => "CrawlURLQueue")
- *   trap(:INT) do
- *     p :called!
- *   end
- *   queue.pull do |record|
- *     # 1. Send SIGINT while blocking the pull operation.
- *     #    The signal handler isn't called.
- *     # 2. Run unblock.rb.
- *     #    The signal handler is called!
- *   end
- *
- *   # unblock.rb
- *   queue = Groonga::Array.open(:name => "CrawlURLQueue")
- *   queue.unblock
- *
- * @see Groonga::Array#pull
- *
- * @overload unblock
- *   @return [void]
- *
- */
-static VALUE
-rb_grn_array_unblock (VALUE self)
-{
-    grn_ctx *context = NULL;
-    grn_obj *table;
-
-    table = SELF(self, &context);
-
-    grn_array_unblock(context, (grn_array *)table);
-
-    return Qnil;
-}
-
 void
 rb_grn_init_array (VALUE mGrn)
 {
@@ -469,7 +201,4 @@ rb_grn_init_array (VALUE mGrn)
                                rb_grn_array_s_create, -1);
 
     rb_define_method(rb_cGrnArray, "add", rb_grn_array_add, -1);
-    rb_define_method(rb_cGrnArray, "push", rb_grn_array_push, 0);
-    rb_define_method(rb_cGrnArray, "pull", rb_grn_array_pull, -1);
-    rb_define_method(rb_cGrnArray, "unblock", rb_grn_array_unblock, 0);
 }

  Modified: test/test-array.rb (+1 -131)
===================================================================
--- test/test-array.rb    2018-01-29 00:30:25 +0900 (c8002532)
+++ test/test-array.rb    2018-01-30 12:33:14 +0900 (1313be1c)
@@ -1,4 +1,4 @@
-# Copyright (C) 2009-2014  Kouhei Sutou <kou �� clear-code.com>
+# Copyright (C) 2009-2018  Kouhei Sutou <kou �� clear-code.com>
 #
 # This library is free software; you can redistribute it and/or
 # modify it under the terms of the GNU Lesser General Public
@@ -157,134 +157,4 @@ class ArrayTest < Test::Unit::TestCase
     user_ids = users.each.collect(&:id)
     assert_equal([1, 2, 3], user_ids)
   end
-
-  class TestPushPull < self
-    def setup
-      @queue = Groonga::Array.create(:name => "Queue")
-      @queue.define_column("content", "ShortText")
-    end
-
-    def teardown
-      @queue = nil
-    end
-
-    def test_block?
-      Tempfile.open("output") do |output|
-        Tempfile.open("blocked_pull.rb") do |pull_rb|
-          pull_rb.puts(pull_rb_source(":block? => true"))
-          pull_rb.close
-
-          pid = spawn({}, RbConfig.ruby, pull_rb.path, :out => output.path)
-          sleep(0.5)
-          @queue.push do |record|
-            record.content = "The first record"
-          end
-          Process.waitpid(pid)
-          assert_equal(<<-EXPECTED_OUTPUT, output.read)
-start
-1, The first record
-done
-EXPECTED_OUTPUT
-        end
-      end
-    end
-
-    def test_not_block?
-      Tempfile.open("output") do |output|
-        Tempfile.open("not_blocked_pull.rb") do |pull_rb|
-          pull_rb.puts(pull_rb_source(":block? => false"))
-          pull_rb.close
-
-          pid = spawn({}, RbConfig.ruby, pull_rb.path, :out => output.path)
-          Process.waitpid(pid)
-          assert_equal(<<-EXPECTED_OUTPUT, output.read)
-start
-done
-EXPECTED_OUTPUT
-
-          @queue.push do |record|
-            record.content = "The first record"
-          end
-          pid = spawn({}, RbConfig.ruby, pull_rb.path, :out => output.path)
-          Process.waitpid(pid)
-          output.rewind
-          assert_equal(<<-EXPECTED_OUTPUT, output.read)
-start
-1, The first record
-done
-EXPECTED_OUTPUT
-        end
-      end
-    end
-
-    def test_unblock
-      IO.pipe do |read_io, write_io|
-        Tempfile.open("not_blocked_pull.rb") do |pull_rb|
-          pull_rb.puts(pull_rb_source(":block? => true"))
-          pull_rb.close
-
-          pid = spawn({}, RbConfig.ruby, pull_rb.path, :out => write_io)
-          assert_equal("start", read_io.gets.chomp)
-          Process.kill(:TERM, pid)
-          @queue.unblock
-          assert_equal("SIGTERM", read_io.gets.chomp)
-          wait_finished(pid)
-          write_io.close
-          assert_equal("done", read_io.read.chomp)
-        end
-      end
-    end
-
-    private
-    def pull_rb_source(options)
-      base_dir = File.expand_path(File.join(File.dirname(__FILE__), ".."))
-      <<-CODE
-$stdout.sync = true
-
-base_dir = #{base_dir.dump}
-
-groonga_command_dir = File.join(base_dir, "..", "groonga-command")
-if File.exist?(groonga_command_dir)
-  $LOAD_PATH.unshift(File.join(groonga_command_dir, "lib"))
-end
-
-groonga_client_dir = File.join(base_dir, "..", "groonga-client")
-if File.exist?(groonga_client_dir)
-  $LOAD_PATH.unshift(File.join(groonga_client_dir, "lib"))
-end
-
-ext_dir = File.join(base_dir, "ext", "groonga")
-lib_dir = File.join(base_dir, "lib")
-
-$LOAD_PATH.unshift(ext_dir)
-$LOAD_PATH.unshift(lib_dir)
-
-require "groonga"
-
-trap(:TERM) do
-  puts("SIGTERM")
-end
-
-puts("start")
-Groonga::Context.default.open_database(#{@database_path.to_s.dump}) do
-  queue = Groonga["Queue"]
-  queue.pull(#{options}) do |record|
-    puts([record.id, record.content].join(", "))
-  end
-end
-puts("done")
-CODE
-    end
-
-    def wait_finished(pid)
-      n_retries = 3
-      n_retries.times do |i|
-        @queue.unblock
-        finished_pid = Process.waitpid(pid, Process::WNOHANG)
-        return if finished_pid
-        sleep((2 ** i) * 0.1)
-      end
-      Process.waitpid(pid)
-    end
-  end
 end
-------------- next part --------------
HTML����������������������������...
URL: https://lists.osdn.me/mailman/archives/groonga-commit/attachments/20180130/45c4df09/attachment-0001.htm 



More information about the Groonga-commit mailing list
Back to archive index