[Groonga-commit] droonga/droonga.org at 47f05e1 [gh-pages] Update ja version of plugin development tutorial

Back to archive index

YUKI Hiroshi null+****@clear*****
Fri Feb 28 12:16:16 JST 2014


YUKI Hiroshi	2014-02-28 12:16:16 +0900 (Fri, 28 Feb 2014)

  New Revision: 47f05e160557214920f1a055f34c041473260b4d
  https://github.com/droonga/droonga.org/commit/47f05e160557214920f1a055f34c041473260b4d

  Message:
    Update ja version of plugin development tutorial

  Modified files:
    _po/ja/tutorial/plugin-development/adapter/index.po
    _po/ja/tutorial/plugin-development/handler/index.po
    _po/ja/tutorial/plugin-development/index.po
    ja/tutorial/plugin-development/adapter/index.md
    ja/tutorial/plugin-development/index.md

  Modified: _po/ja/tutorial/plugin-development/adapter/index.po (+10 -4)
===================================================================
--- _po/ja/tutorial/plugin-development/adapter/index.po    2014-02-28 12:11:33 +0900 (8a494d1)
+++ _po/ja/tutorial/plugin-development/adapter/index.po    2014-02-28 12:16:16 +0900 (59927c7)
@@ -46,7 +46,7 @@ msgstr ""
 
 msgid ""
 "First, let's study basics with a simple logger plugin named `sample-logger` af"
-"fects on the adaption phase."
+"fects at the adaption phase."
 msgstr ""
 
 msgid ""
@@ -112,7 +112,10 @@ msgid ""
 "module Droonga\n"
 "  module Plugins\n"
 "    module SampleLoggerPlugin\n"
-"      Plugin.registry.register(\"sample-logger\", self)"
+"      extend Plugin"
+msgstr ""
+
+msgid "      registry.register(\"sample-logger\", self)"
 msgstr ""
 
 msgid ""
@@ -131,7 +134,10 @@ msgstr ""
 msgid ""
 " * The `sample-logger` is the name of the plugin itself. You'll use it in your"
 " `catalog.json`, to activate the plugin.\n"
-" * As the example above, you must define your plugin as a module."
+" * As the example above, you must define your plugin as a module.\n"
+" * Behaviors at the adaption phase is defined a class called *adapter*.\n"
+"   An adapter class must be defined as a subclass of the `Droonga::Adapter`, u"
+"nder the namespace of the plugin module."
 msgstr ""
 
 msgid "### Activate the plugin with `catalog.json`"
@@ -159,7 +165,7 @@ msgstr ""
 
 msgid ""
 "Note: you must place `\"sample-logger\"` before `\"search\"`, because the `sample-"
-"logger` plugin depends on the `search`. Droonga Engine applies plugins on the "
+"logger` plugin depends on the `search`. Droonga Engine applies plugins at the "
 "adaption phase in the order defined in the `catalog.json`, so you must resolve"
 " plugin dependencies by your hand (for now)."
 msgstr ""

  Modified: _po/ja/tutorial/plugin-development/handler/index.po (+466 -305)
===================================================================
--- _po/ja/tutorial/plugin-development/handler/index.po    2014-02-28 12:11:33 +0900 (523146c)
+++ _po/ja/tutorial/plugin-development/handler/index.po    2014-02-28 12:16:16 +0900 (e782344)
@@ -9,14 +9,11 @@ msgstr ""
 
 msgid ""
 "---\n"
-"title: \"Plugin: Handle requests\"\n"
+"title: \"Plugin: Handle requests on all partitions\"\n"
 "layout: en\n"
 "---"
 msgstr ""
 
-msgid "!!! WORK IN PROGRESS !!!"
-msgstr ""
-
 msgid ""
 "* TOC\n"
 "{:toc}"
@@ -26,55 +23,132 @@ msgid "## The goal of this tutorial"
 msgstr "## チュートリアルのゴール"
 
 msgid ""
-"This tutorial aims to help you to learn how to develop plugins\n"
-"which extends operations in handle phrase."
+"This tutorial aims to help you to learn how to develop plugins which do someth"
+"ing dispersively for/in each partition, around the handling phase."
 msgstr ""
 
 msgid "## Precondition"
 msgstr "## 前提条件"
 
-msgid "* You must complete [Modify requests and responses tutorial][adapter]."
+msgid "* You must complete the [tutorial for the adaption phase][adapter]."
 msgstr ""
 
-msgid "## Handling phase"
+msgid "## Handling of incoming messages"
 msgstr ""
 
 msgid ""
-"The handling phase is the phase that the actual storage access is happen.\n"
-"As Droonga is a distributed system, handler phase is done in multiple partitio"
-"ns."
+"When an incoming message is transferred from the adaption phase, the Droonga E"
+"ngine enters into the *processing phase*."
 msgstr ""
 
 msgid ""
-"Here, in this tutorial, we are going to replace the handling phase of `search`"
-" command for explanation. This breaks the `search` command. So this is not use"
-"ful in practice, but it will help you to learn how Droonga works."
+"In the processing phase, the Droonga Engine processes incoming messages step b"
+"y step.\n"
+"One *step* is constructed from some sub phases: *planning phase*, *distributio"
+"n phase*, *handling phase*, and *collection phase*."
 msgstr ""
 
 msgid ""
-"In practice, we need to *extend* Droonga. In this case, we need to add a new c"
-"ommand which does not conflict with the existing commands. To do so, you need "
-"to learn not only how to handle messages but also how to distribute messages t"
-"o handlers and collect messages from them. Proceed to [Distribute requests and"
-" collect responses][] after this tutorial completed."
+" * At the *planning phase*, the Droonga Engine generates multiple sub steps to"
+" process an incoming message.\n"
+"   In simple cases, you don't have to write codes for this phase, then there i"
+"s just one sub step to handle the message.\n"
+" * At the *distribution phase*, the Droonga Engine distributes the message to "
+"multiple partitions.\n"
+"   (It is completely done by the Droonga Engine itself, so this phase is not p"
+"luggable.)\n"
+" * At the *handling phase*, *each partition simply processes only one distribu"
+"ted message as its input, and returns a result.*\n"
+"   This is the time that actual storage accesses happen.\n"
+"   Actually, some commands (`search`, `add`, `create_table` and so on) access "
+"to the storage at the time.\n"
+" * At the *collection phase*, the Droonga Engine collects results from partiti"
+"ons to one unified result.\n"
+"   There are some useful generic collectors, so you don't have to write codes "
+"for this phase in most cases."
 msgstr ""
 
-msgid "TODO fix the link to \"Distribute requests and collect responses\" tutorial"
+msgid ""
+"After all steps are finished, the Droonga Engine transfers the result to the p"
+"ost adaption phase."
 msgstr ""
 
-msgid "## Directory Structure"
+msgid ""
+"A class to define operations at the handling phase is called *handler*.\n"
+"Put simply, adding of a new handler means adding a new command."
+msgstr ""
+
+msgid "## Design a read-only command `countRecords`"
 msgstr ""
 
 msgid ""
-"The directory structure for plugins are in same rule as explained in [Modify r"
-"equests and responses tutorial][adapter]."
+"Here, in this tutorial, we are going to add a new custom `countRecords` comman"
+"d.\n"
+"At first, let's design it."
+msgstr ""
+
+msgid ""
+"The command reports the number of records about a specified table, for each pa"
+"rtition.\n"
+"So it will help you to know how records are distributed in the cluster.\n"
+"Nothing is changed by the command, so it is a *read-only command*."
+msgstr ""
+
+msgid "The request must have the name of one table, like:"
+msgstr ""
+
+msgid ""
+"~~~json\n"
+"{\n"
+"  \"dataset\" : \"Starbucks\",\n"
+"  \"type\"    : \"countRecords\",\n"
+"  \"body\"    : {\n"
+"    \"table\": \"Store\"\n"
+"  }\n"
+"}\n"
+"~~~"
+msgstr ""
+
+msgid ""
+"Create a JSON file `count-records.json` with the content above.\n"
+"We'll use it for testing."
+msgstr ""
+
+msgid ""
+"The response must have number of records in the table, for each partition.\n"
+"They can be appear in an array, like:"
+msgstr ""
+
+msgid ""
+"~~~json\n"
+"{\n"
+"  \"inReplyTo\": \"(message id)\",\n"
+"  \"statusCode\": 200,\n"
+"  \"type\": \"countRecords.result\",\n"
+"  \"body\": [10, 10]\n"
+"}\n"
+"~~~"
 msgstr ""
 
 msgid ""
-"Now let's create `sample-logger` plugin again. This will act almost same as [M"
-"odify requests and responses tutorial][adapter] version, except the phase in w"
-"hich the plugin works. We need to put `sample-logger.rb` to `lib/droonga/plugi"
-"ns/sample-logger.rb`. The directory tree will be like this:"
+"If there are 2 partitions and 20 records are stored evenly, the array will hav"
+"e two elements like above.\n"
+"It means that a partition has 10 records and another one also has 10 records."
+msgstr ""
+
+msgid ""
+"We're going to create a plugin to accept such requests and return such respons"
+"es."
+msgstr ""
+
+msgid "### Directory structure"
+msgstr ""
+
+msgid ""
+"The directory structure for plugins are in same rule as explained in the [tuto"
+"rial for the adaption phase][adapter].\n"
+"Now let's create the `count-records` plugin, as the file `count-records.rb`. T"
+"he directory tree will be:"
 msgstr ""
 
 msgid ""
@@ -82,17 +156,14 @@ msgid ""
 "lib\n"
 "└── droonga\n"
 "    └── plugins\n"
-"            └── sample-logger.rb\n"
+"            └── count-records.rb\n"
 "~~~"
 msgstr ""
 
-msgid "## Create a plugin"
-msgstr ""
-
-msgid "Create a plugin as follows:"
+msgid "Then, create a skelton of a plugin as follows:"
 msgstr ""
 
-msgid "lib/droonga/plugins/sample-logger.rb:"
+msgid "lib/droonga/plugins/count-records.rb:"
 msgstr ""
 
 msgid ""
@@ -103,19 +174,62 @@ msgstr ""
 msgid ""
 "module Droonga\n"
 "  module Plugins\n"
-"    module SampleLoggerPlugin\n"
-"      Plugin.registry.register(\"sample-logger\", self)"
+"    module CountRecordsPlugin\n"
+"      Plugin.registry.register(\"count-records\", self)\n"
+"    end\n"
+"  end\n"
+"end\n"
+"~~~"
+msgstr ""
+
+msgid "### Define a \"step\" for the command"
+msgstr ""
+
+msgid "Define a \"step\" for the new `countRecords` command, in your plugin. Like:"
 msgstr ""
 
 msgid ""
-"      class Handler < Droonga::Handler\n"
-"        message.type = \"search\""
+"module Droonga\n"
+"  module Plugins\n"
+"    module CountRecordsPlugin\n"
+"      Plugin.registry.register(\"count-records\", self)"
 msgstr ""
 
 msgid ""
-"        def handle(message, messenger)\n"
-"          $log.info \"Droonga::Plugins::SampleLoggerPlugin\", :message => messag"
-"e\n"
+"      define_single_step do |step|\n"
+"        step.name = \"countRecords\"\n"
+"      end\n"
+"    end\n"
+"  end\n"
+"end\n"
+"~~~"
+msgstr ""
+
+msgid ""
+"The `step.name` equals to the name of the command itself.\n"
+"Currently we just define the name of the command.\n"
+"That's all."
+msgstr ""
+
+msgid "### Define the handling logic"
+msgstr ""
+
+msgid ""
+"The command has no handler, so it does nothing yet.\n"
+"Let's define the behavior."
+msgstr ""
+
+msgid ""
+"      define_single_step do |step|\n"
+"        step.name = \"countRecords\"\n"
+"        step.handler = :Handler\n"
+"      end"
+msgstr ""
+
+msgid ""
+"      class Handler < Droonga::Handler\n"
+"        def handle(message)\n"
+"          [0]\n"
 "        end\n"
 "      end\n"
 "    end\n"
@@ -124,12 +238,58 @@ msgid ""
 "~~~"
 msgstr ""
 
-msgid "## Activate the plugin with `catalog.json`"
+msgid "The class `Handler` is a handler class for our new command."
+msgstr ""
+
+msgid ""
+" * It must inherit a builtin-class `Droonga::Handler`.\n"
+" * It implements the logic to handle requests.\n"
+"   Its instance method `#handle` actually handles requests."
+msgstr ""
+
+msgid ""
+"Currently the handler does nothing and returns an array of a number.\n"
+"The returned value is used to construct the response body."
+msgstr ""
+
+msgid ""
+"The handler is bound to the step with the configuration `step.handler`.\n"
+"Because we define the class `Handler` after `define_single_step`, we specify t"
+"he handler class with a symbol `:Handler`.\n"
+"If you define the handler class before `define_single_step`, then you can writ"
+"e as `step.handler = Handler` simply.\n"
+"Moreover, a class path string like `\"OtherPlugin::Handler\"` is also available."
+msgstr ""
+
+msgid ""
+"Then, we also have to bind a collector to the step, with the configuration `st"
+"ep.collector`."
+msgstr ""
+
+msgid ""
+"~~~ruby\n"
+"(snip)\n"
+"      define_single_step do |step|\n"
+"        step.name = \"countRecords\"\n"
+"        step.handler = :Handler\n"
+"        step.collector = SumCollector\n"
+"      end\n"
+"(snip)\n"
+"~~~"
+msgstr ""
+
+msgid ""
+"The `SumCollector` is one of built-in collectors.\n"
+"It merges results retuned from handler instances for each partition to one res"
+"ult."
+msgstr ""
+
+msgid "### Activate the plugin with `catalog.json`"
 msgstr ""
 
 msgid ""
-"Update catalog.json to activate this plugin. Add `\"sample-logger\"` to `\"plugin"
-"s\"`."
+"Update catalog.json to activate this plugin.\n"
+"Add `\"count-records\"` to `\"plugins\"`."
 msgstr ""
 
 msgid ""
@@ -138,17 +298,18 @@ msgid ""
 "      \"datasets\": {\n"
 "        \"Starbucks\": {\n"
 "          (snip)\n"
-"          \"plugins\": [\"sample-logger\", \"groonga\", \"crud\", \"search\"],\n"
+"          \"plugins\": [\"count-records\", \"groonga\", \"crud\", \"search\"],\n"
 "(snip)\n"
 "~~~"
 msgstr ""
 
-msgid "## Run"
+msgid "### Run and test"
 msgstr ""
 
 msgid ""
-"Let's get Droonga started. Note that you need to specify ./lib directory in RU"
-"BYLIB environment variable in order to make ruby possible to find your plugin."
+"Let's get Droonga started.\n"
+"Note that you need to specify ./lib directory in RUBYLIB environment variable "
+"in order to make ruby possible to find your plugin."
 msgstr ""
 
 msgid ""
@@ -157,343 +318,340 @@ msgid ""
 "luentd.pid"
 msgstr ""
 
-msgid "## Test"
+msgid "Then, send a message for the `countRecords` command to the Droonga Engine."
 msgstr ""
 
 msgid ""
-"Send a search request to Droonga Engine. Use `search-columbus.json` same as of"
-" [Modify requests and responses tutorial][adapter]."
+"~~~\n"
+"# droonga-request --tag starbucks count-records.json\n"
+"Elapsed time: 0.01494\n"
+"[\n"
+"  \"droonga.message\",\n"
+"  1392621168,\n"
+"  {\n"
+"    \"inReplyTo\": \"1392621168.0119512\",\n"
+"    \"statusCode\": 200,\n"
+"    \"type\": \"countRecords.result\",\n"
+"    \"body\": [0, 0, 0]\n"
+"  }\n"
+"]\n"
+"~~~"
 msgstr ""
 
 msgid ""
-"~~~\n"
-"# droonga-request --tag starbucks search-columbus.json\n"
+"You'll get a response message like above.\n"
+"Look at these points:"
+msgstr ""
+
+msgid ""
+" * The `type` of the response becomes `countRecords.result`.\n"
+"   It is automatically named by the Droonga Engine.\n"
+" * The format of the `body` is same to the returned value of the handler's `ha"
+"ndle` method."
+msgstr ""
+
+msgid "There are 3 elements in the array. Why?"
+msgstr ""
+
+msgid ""
+" * Remember that we have configured the `Starbucks` dataset to use 3 partition"
+"s (and each has 2 replicas) in the `catalog.json` of [the basic tutorial][basi"
+"c].\n"
+" * Because it is a read-only command, an incoming message is distributed only "
+"to paritions, not to replicas.\n"
+"   So there are only 3 results, not 6.\n"
+"   (TODO: I have to add a figure to indicate active nodes: [000, 001, 010, 011"
+", 020, 021] => [000, 011, 020])\n"
+" * The `SumCollector` collects them.\n"
+"   Those 3 results are joined to just one array by the collector."
+msgstr ""
+
+msgid "As the result, just one array with 3 elements appears in the response message."
+msgstr ""
+
+msgid "### Read-only access to the storage"
+msgstr ""
+
+msgid ""
+"Now, each instance of the handler class always returns `[0]` as its result.\n"
+"Let's implement codes to count up the number of records from the actual storag"
+"e."
+msgstr ""
+
+msgid ""
+"~~~ruby\n"
+"(snip)\n"
+"      class Handler < Droonga::Handler\n"
+"        def handle(message)\n"
+"          table_name = message[\"body\"][\"table\"]\n"
+"          table = @context[table_name]\n"
+"          count = table.size\n"
+"          [count]\n"
+"        end\n"
+"      end\n"
+"(snip)\n"
 "~~~"
 msgstr ""
 
 msgid ""
-"You will see no output for `droonga-request` execution because out `sample-log"
-"ger` plugin traps the `add` request."
+"The instance variable `@context` is an instance of `Groonga::Context` for the "
+"storage of the partition.\n"
+"See the [class reference of Rroonga][Groonga::Context].\n"
+"You can use any feature of Rroonga via `@context`.\n"
+"For now, we simply access to the table itself by its name and read the value o"
+"f its `size` method - it returns the number of records."
 msgstr ""
 
-msgid "Instead, you will see something like these lines in `fluentd.log`:"
+msgid ""
+"Then, test it.\n"
+"Restart the Droonga Engine and send the request again."
 msgstr ""
 
 msgid ""
 "~~~\n"
-"2014-02-17 16:25:23 +0900 [info]: Droonga::Plugins::SampleLoggerPlugin message"
-"=#<Droonga::HandlerMessage:0x007f9a7f0987a8 @raw={\"dataset\"=>\"Starbucks\", \"typ"
-"e\"=>\"search\", \"body\"=>{\"id\"=>\"localhost:24224/starbucks.#0\", \"task\"=>{\"route\"="
-">\"localhost:24224/starbucks.011\", \"step\"=>{\"command\"=>\"search\", \"dataset\"=>\"St"
-"arbucks\", \"body\"=>{\"queries\"=>{\"stores\"=>{\"source\"=>\"Store\", \"condition\"=>{\"qu"
-"ery\"=>\"Columbus\", \"matchTo\"=>\"_key\"}, \"output\"=>{\"elements\"=>[\"startTime\", \"el"
-"apsedTime\", \"count\", \"attributes\", \"records\"], \"attributes\"=>[\"_key\"], \"limit\""
-"=>-1}}}}, \"type\"=>\"broadcast\", \"outputs\"=>[\"errors\", \"stores\"], \"replica\"=>\"ra"
-"ndom\", \"routes\"=>[\"localhost:24224/starbucks.001\", \"localhost:24224/starbucks."
-"011\", \"localhost:24224/starbucks.020\"], \"n_of_expects\"=>0, \"descendants\"=>{\"er"
-"rors\"=>[\"localhost:24224/starbucks.#0\"], \"stores\"=>[\"localhost:24224/starbucks"
-".#0\"]}}, \"n_of_inputs\"=>0, \"values\"=>{}}, \"descendants\"=>{\"errors\"=>[\"localhos"
-"t:24224/starbucks\"], \"stores\"=>[\"localhost:24224/starbucks\"]}}, \"replyTo\"=>{\"t"
-"ype\"=>\"search.result\", \"to\"=>\"127.0.0.1:50410/droonga\"}, \"id\"=>\"1392621923.903"
-"868\", \"date\"=>\"2014-02-17 16:25:23 +0900\", \"appliedAdapters\"=>[\"Droonga::Plugi"
-"ns::Error::Adapter\"]}, @body={\"id\"=>\"localhost:24224/starbucks.#0\", \"task\"=>{\""
-"route\"=>\"localhost:24224/starbucks.011\", \"step\"=>{\"command\"=>\"search\", \"datase"
-"t\"=>\"Starbucks\", \"body\"=>{\"queries\"=>{\"stores\"=>{\"source\"=>\"Store\", \"condition"
-"\"=>{\"query\"=>\"Columbus\", \"matchTo\"=>\"_key\"}, \"output\"=>{\"elements\"=>[\"startTim"
-"e\", \"elapsedTime\", \"count\", \"attributes\", \"records\"], \"attributes\"=>[\"_key\"], "
-"\"limit\"=>-1}}}}, \"type\"=>\"broadcast\", \"outputs\"=>[\"errors\", \"stores\"], \"replic"
-"a\"=>\"random\", \"routes\"=>[\"localhost:24224/starbucks.001\", \"localhost:24224/sta"
-"rbucks.011\", \"localhost:24224/starbucks.020\"], \"n_of_expects\"=>0, \"descendants"
-"\"=>{\"errors\"=>[\"localhost:24224/starbucks.#0\"], \"stores\"=>[\"localhost:24224/st"
-"arbucks.#0\"]}}, \"n_of_inputs\"=>0, \"values\"=>{}}, \"descendants\"=>{\"errors\"=>[\"l"
-"ocalhost:24224/starbucks\"], \"stores\"=>[\"localhost:24224/starbucks\"]}}, @task={"
-"\"route\"=>\"localhost:24224/starbucks.011\", \"step\"=>{\"command\"=>\"search\", \"datas"
-"et\"=>\"Starbucks\", \"body\"=>{\"queries\"=>{\"stores\"=>{\"source\"=>\"Store\", \"conditio"
-"n\"=>{\"query\"=>\"Columbus\", \"matchTo\"=>\"_key\"}, \"output\"=>{\"elements\"=>[\"startTi"
-"me\", \"elapsedTime\", \"count\", \"attributes\", \"records\"], \"attributes\"=>[\"_key\"],"
-" \"limit\"=>-1}}}}, \"type\"=>\"broadcast\", \"outputs\"=>[\"errors\", \"stores\"], \"repli"
-"ca\"=>\"random\", \"routes\"=>[\"localhost:24224/starbucks.001\", \"localhost:24224/st"
-"arbucks.011\", \"localhost:24224/starbucks.020\"], \"n_of_expects\"=>0, \"descendant"
-"s\"=>{\"errors\"=>[\"localhost:24224/starbucks.#0\"], \"stores\"=>[\"localhost:24224/s"
-"tarbucks.#0\"]}}, \"n_of_inputs\"=>0, \"values\"=>{}}, @step={\"command\"=>\"search\", "
-"\"dataset\"=>\"Starbucks\", \"body\"=>{\"queries\"=>{\"stores\"=>{\"source\"=>\"Store\", \"co"
-"ndition\"=>{\"query\"=>\"Columbus\", \"matchTo\"=>\"_key\"}, \"output\"=>{\"elements\"=>[\"s"
-"tartTime\", \"elapsedTime\", \"count\", \"attributes\", \"records\"], \"attributes\"=>[\"_"
-"key\"], \"limit\"=>-1}}}}, \"type\"=>\"broadcast\", \"outputs\"=>[\"errors\", \"stores\"], "
-"\"replica\"=>\"random\", \"routes\"=>[\"localhost:24224/starbucks.001\", \"localhost:24"
-"224/starbucks.011\", \"localhost:24224/starbucks.020\"], \"n_of_expects\"=>0, \"desc"
-"endants\"=>{\"errors\"=>[\"localhost:24224/starbucks.#0\"], \"stores\"=>[\"localhost:2"
-"4224/starbucks.#0\"]}}>\n"
-"2014-02-17 16:25:23 +0900 [info]: Droonga::Plugins::SampleLoggerPlugin message"
-"=#<Droonga::HandlerMessage:0x007f9a7f060970 @raw={\"dataset\"=>\"Starbucks\", \"typ"
-"e\"=>\"search\", \"body\"=>{\"id\"=>\"localhost:24224/starbucks.#0\", \"task\"=>{\"route\"="
-">\"localhost:24224/starbucks.020\", \"step\"=>{\"command\"=>\"search\", \"dataset\"=>\"St"
-"arbucks\", \"body\"=>{\"queries\"=>{\"stores\"=>{\"source\"=>\"Store\", \"condition\"=>{\"qu"
-"ery\"=>\"Columbus\", \"matchTo\"=>\"_key\"}, \"output\"=>{\"elements\"=>[\"startTime\", \"el"
-"apsedTime\", \"count\", \"attributes\", \"records\"], \"attributes\"=>[\"_key\"], \"limit\""
-"=>-1}}}}, \"type\"=>\"broadcast\", \"outputs\"=>[\"errors\", \"stores\"], \"replica\"=>\"ra"
-"ndom\", \"routes\"=>[\"localhost:24224/starbucks.001\", \"localhost:24224/starbucks."
-"011\", \"localhost:24224/starbucks.020\"], \"n_of_expects\"=>0, \"descendants\"=>{\"er"
-"rors\"=>[\"localhost:24224/starbucks.#0\"], \"stores\"=>[\"localhost:24224/starbucks"
-".#0\"]}}, \"n_of_inputs\"=>0, \"values\"=>{}}, \"descendants\"=>{\"errors\"=>[\"localhos"
-"t:24224/starbucks\"], \"stores\"=>[\"localhost:24224/starbucks\"]}}, \"replyTo\"=>{\"t"
-"ype\"=>\"search.result\", \"to\"=>\"127.0.0.1:50410/droonga\"}, \"id\"=>\"1392621923.903"
-"868\", \"date\"=>\"2014-02-17 16:25:23 +0900\", \"appliedAdapters\"=>[\"Droonga::Plugi"
-"ns::Error::Adapter\"]}, @body={\"id\"=>\"localhost:24224/starbucks.#0\", \"task\"=>{\""
-"route\"=>\"localhost:24224/starbucks.020\", \"step\"=>{\"command\"=>\"search\", \"datase"
-"t\"=>\"Starbucks\", \"body\"=>{\"queries\"=>{\"stores\"=>{\"source\"=>\"Store\", \"condition"
-"\"=>{\"query\"=>\"Columbus\", \"matchTo\"=>\"_key\"}, \"output\"=>{\"elements\"=>[\"startTim"
-"e\", \"elapsedTime\", \"count\", \"attributes\", \"records\"], \"attributes\"=>[\"_key\"], "
-"\"limit\"=>-1}}}}, \"type\"=>\"broadcast\", \"outputs\"=>[\"errors\", \"stores\"], \"replic"
-"a\"=>\"random\", \"routes\"=>[\"localhost:24224/starbucks.001\", \"localhost:24224/sta"
-"rbucks.011\", \"localhost:24224/starbucks.020\"], \"n_of_expects\"=>0, \"descendants"
-"\"=>{\"errors\"=>[\"localhost:24224/starbucks.#0\"], \"stores\"=>[\"localhost:24224/st"
-"arbucks.#0\"]}}, \"n_of_inputs\"=>0, \"values\"=>{}}, \"descendants\"=>{\"errors\"=>[\"l"
-"ocalhost:24224/starbucks\"], \"stores\"=>[\"localhost:24224/starbucks\"]}}, @task={"
-"\"route\"=>\"localhost:24224/starbucks.020\", \"step\"=>{\"command\"=>\"search\", \"datas"
-"et\"=>\"Starbucks\", \"body\"=>{\"queries\"=>{\"stores\"=>{\"source\"=>\"Store\", \"conditio"
-"n\"=>{\"query\"=>\"Columbus\", \"matchTo\"=>\"_key\"}, \"output\"=>{\"elements\"=>[\"startTi"
-"me\", \"elapsedTime\", \"count\", \"attributes\", \"records\"], \"attributes\"=>[\"_key\"],"
-" \"limit\"=>-1}}}}, \"type\"=>\"broadcast\", \"outputs\"=>[\"errors\", \"stores\"], \"repli"
-"ca\"=>\"random\", \"routes\"=>[\"localhost:24224/starbucks.001\", \"localhost:24224/st"
-"arbucks.011\", \"localhost:24224/starbucks.020\"], \"n_of_expects\"=>0, \"descendant"
-"s\"=>{\"errors\"=>[\"localhost:24224/starbucks.#0\"], \"stores\"=>[\"localhost:24224/s"
-"tarbucks.#0\"]}}, \"n_of_inputs\"=>0, \"values\"=>{}}, @step={\"command\"=>\"search\", "
-"\"dataset\"=>\"Starbucks\", \"body\"=>{\"queries\"=>{\"stores\"=>{\"source\"=>\"Store\", \"co"
-"ndition\"=>{\"query\"=>\"Columbus\", \"matchTo\"=>\"_key\"}, \"output\"=>{\"elements\"=>[\"s"
-"tartTime\", \"elapsedTime\", \"count\", \"attributes\", \"records\"], \"attributes\"=>[\"_"
-"key\"], \"limit\"=>-1}}}}, \"type\"=>\"broadcast\", \"outputs\"=>[\"errors\", \"stores\"], "
-"\"replica\"=>\"random\", \"routes\"=>[\"localhost:24224/starbucks.001\", \"localhost:24"
-"224/starbucks.011\", \"localhost:24224/starbucks.020\"], \"n_of_expects\"=>0, \"desc"
-"endants\"=>{\"errors\"=>[\"localhost:24224/starbucks.#0\"], \"stores\"=>[\"localhost:2"
-"4224/starbucks.#0\"]}}>\n"
-"2014-02-17 16:25:23 +0900 [info]: Droonga::Plugins::SampleLoggerPlugin message"
-"=#<Droonga::HandlerMessage:0x007f9a7f069c50 @raw={\"dataset\"=>\"Starbucks\", \"typ"
-"e\"=>\"search\", \"body\"=>{\"id\"=>\"localhost:24224/starbucks.#0\", \"task\"=>{\"route\"="
-">\"localhost:24224/starbucks.001\", \"step\"=>{\"command\"=>\"search\", \"dataset\"=>\"St"
-"arbucks\", \"body\"=>{\"queries\"=>{\"stores\"=>{\"source\"=>\"Store\", \"condition\"=>{\"qu"
-"ery\"=>\"Columbus\", \"matchTo\"=>\"_key\"}, \"output\"=>{\"elements\"=>[\"startTime\", \"el"
-"apsedTime\", \"count\", \"attributes\", \"records\"], \"attributes\"=>[\"_key\"], \"limit\""
-"=>-1}}}}, \"type\"=>\"broadcast\", \"outputs\"=>[\"errors\", \"stores\"], \"replica\"=>\"ra"
-"ndom\", \"routes\"=>[\"localhost:24224/starbucks.001\", \"localhost:24224/starbucks."
-"011\", \"localhost:24224/starbucks.020\"], \"n_of_expects\"=>0, \"descendants\"=>{\"er"
-"rors\"=>[\"localhost:24224/starbucks.#0\"], \"stores\"=>[\"localhost:24224/starbucks"
-".#0\"]}}, \"n_of_inputs\"=>0, \"values\"=>{}}, \"descendants\"=>{\"errors\"=>[\"localhos"
-"t:24224/starbucks\"], \"stores\"=>[\"localhost:24224/starbucks\"]}}, \"replyTo\"=>{\"t"
-"ype\"=>\"search.result\", \"to\"=>\"127.0.0.1:50410/droonga\"}, \"id\"=>\"1392621923.903"
-"868\", \"date\"=>\"2014-02-17 16:25:23 +0900\", \"appliedAdapters\"=>[\"Droonga::Plugi"
-"ns::Error::Adapter\"]}, @body={\"id\"=>\"localhost:24224/starbucks.#0\", \"task\"=>{\""
-"route\"=>\"localhost:24224/starbucks.001\", \"step\"=>{\"command\"=>\"search\", \"datase"
-"t\"=>\"Starbucks\", \"body\"=>{\"queries\"=>{\"stores\"=>{\"source\"=>\"Store\", \"condition"
-"\"=>{\"query\"=>\"Columbus\", \"matchTo\"=>\"_key\"}, \"output\"=>{\"elements\"=>[\"startTim"
-"e\", \"elapsedTime\", \"count\", \"attributes\", \"records\"], \"attributes\"=>[\"_key\"], "
-"\"limit\"=>-1}}}}, \"type\"=>\"broadcast\", \"outputs\"=>[\"errors\", \"stores\"], \"replic"
-"a\"=>\"random\", \"routes\"=>[\"localhost:24224/starbucks.001\", \"localhost:24224/sta"
-"rbucks.011\", \"localhost:24224/starbucks.020\"], \"n_of_expects\"=>0, \"descendants"
-"\"=>{\"errors\"=>[\"localhost:24224/starbucks.#0\"], \"stores\"=>[\"localhost:24224/st"
-"arbucks.#0\"]}}, \"n_of_inputs\"=>0, \"values\"=>{}}, \"descendants\"=>{\"errors\"=>[\"l"
-"ocalhost:24224/starbucks\"], \"stores\"=>[\"localhost:24224/starbucks\"]}}, @task={"
-"\"route\"=>\"localhost:24224/starbucks.001\", \"step\"=>{\"command\"=>\"search\", \"datas"
-"et\"=>\"Starbucks\", \"body\"=>{\"queries\"=>{\"stores\"=>{\"source\"=>\"Store\", \"conditio"
-"n\"=>{\"query\"=>\"Columbus\", \"matchTo\"=>\"_key\"}, \"output\"=>{\"elements\"=>[\"startTi"
-"me\", \"elapsedTime\", \"count\", \"attributes\", \"records\"], \"attributes\"=>[\"_key\"],"
-" \"limit\"=>-1}}}}, \"type\"=>\"broadcast\", \"outputs\"=>[\"errors\", \"stores\"], \"repli"
-"ca\"=>\"random\", \"routes\"=>[\"localhost:24224/starbucks.001\", \"localhost:24224/st"
-"arbucks.011\", \"localhost:24224/starbucks.020\"], \"n_of_expects\"=>0, \"descendant"
-"s\"=>{\"errors\"=>[\"localhost:24224/starbucks.#0\"], \"stores\"=>[\"localhost:24224/s"
-"tarbucks.#0\"]}}, \"n_of_inputs\"=>0, \"values\"=>{}}, @step={\"command\"=>\"search\", "
-"\"dataset\"=>\"Starbucks\", \"body\"=>{\"queries\"=>{\"stores\"=>{\"source\"=>\"Store\", \"co"
-"ndition\"=>{\"query\"=>\"Columbus\", \"matchTo\"=>\"_key\"}, \"output\"=>{\"elements\"=>[\"s"
-"tartTime\", \"elapsedTime\", \"count\", \"attributes\", \"records\"], \"attributes\"=>[\"_"
-"key\"], \"limit\"=>-1}}}}, \"type\"=>\"broadcast\", \"outputs\"=>[\"errors\", \"stores\"], "
-"\"replica\"=>\"random\", \"routes\"=>[\"localhost:24224/starbucks.001\", \"localhost:24"
-"224/starbucks.011\", \"localhost:24224/starbucks.020\"], \"n_of_expects\"=>0, \"desc"
-"endants\"=>{\"errors\"=>[\"localhost:24224/starbucks.#0\"], \"stores\"=>[\"localhost:2"
-"4224/starbucks.#0\"]}}>\n"
+"# kill $(cat fluentd.pid)\n"
+"# RUBYLIB=./lib fluentd --config fluentd.conf --log fluentd.log --daemon fluen"
+"td.pid\n"
+"# droonga-request --tag starbucks count-records.json\n"
+"Elapsed time: 0.01494\n"
+"[\n"
+"  \"droonga.message\",\n"
+"  1392621168,\n"
+"  {\n"
+"    \"inReplyTo\": \"1392621168.0119512\",\n"
+"    \"statusCode\": 200,\n"
+"    \"type\": \"countRecords.result\",\n"
+"    \"body\": [12, 12, 11]\n"
+"  }\n"
+"]\n"
 "~~~"
 msgstr ""
 
-msgid "Note that three lines are shown for only one request. What is happening?"
+msgid "Because there are totally 35 records, they are stored evenly like above."
+msgstr ""
+
+msgid "## Design a read-write command `deleteStores`"
+msgstr ""
+
+msgid "Next, let's add another new custom command `deleteStores`."
 msgstr ""
 
 msgid ""
-"Remember that we have configured `Starbucks` dataset to use three partitions ("
-"and each has two replicas) in `catalog.json` of [the basic tutorial][basic]."
+"The command deletes records of the `Store` table, from the storage.\n"
+"Because it modifies something in existing storage, it is a *read-write command"
+"*."
+msgstr ""
+
+msgid "The request must have the condition to select records to be deleted, like:"
 msgstr ""
 
 msgid ""
-"The `search` request is dispatched to three partitions and passed into handlin"
-"g phase for each partition. That is because we saw three lines for one request"
-"."
+"~~~json\n"
+"{\n"
+"  \"dataset\" : \"Starbucks\",\n"
+"  \"type\"    : \"deleteStores\",\n"
+"  \"body\"    : {\n"
+"    \"keyword\": \"Broardway\"\n"
+"  }\n"
+"}\n"
+"~~~"
 msgstr ""
 
 msgid ""
-"The messages shown is in internal format, which is transformed from the reques"
-"t you've sent.\n"
-"You can see your search request is distributed to partitions `localhost:24224/"
-"starbucks.001`, `localhost:24224/starbucks.011` and `localhost:24224/starbucks"
-".020` from `\"routes\"`."
+"Any record including the given keyword `\"Broadway\"` in its `\"key\"` is deleted "
+"from the storage of all partitions."
 msgstr ""
 
 msgid ""
-"In `search` case, it is enough to use one replica per one partition because re"
-"plicas for a partition are expected to have the exactly same contents.\n"
-"So the planner ordered distributor to choose one replica randomly."
+"Create a JSON file `delete-stores-broadway.json` with the content above.\n"
+"We'll use it for testing."
+msgstr ""
+
+msgid "The response must have a boolean value to indicate \"success\" or \"fail\", like:"
 msgstr ""
 
-msgid "## Trap \"add\" command"
+msgid ""
+"~~~json\n"
+"{\n"
+"  \"inReplyTo\": \"(message id)\",\n"
+"  \"statusCode\": 200,\n"
+"  \"type\": \"deleteStores.result\",\n"
+"  \"body\": true\n"
+"}\n"
+"~~~"
 msgstr ""
 
 msgid ""
-"We have seen how distributed search is done from the view point of handling ph"
-"ase so far.\n"
-"How about `\"add\"` command?"
+"If the request is successfully processed, the `body` becomes `true`. Otherwise"
+" `false`.\n"
+"The `body` is just one boolean value, because we don't have to receive multipl"
+"e results from partitions."
 msgstr ""
 
-msgid "Update `smaple-logger` plugin to trap `\"add\"` message instead of `\"search\"`."
+msgid "### Directory Structure"
+msgstr ""
+
+msgid ""
+"Now let's create the `delete-stores` plugin, as the file `delete-stores.rb`. T"
+"he directory tree will be:"
 msgstr ""
 
 msgid ""
 "~~~\n"
-"require \"droonga/plugin\""
+"lib\n"
+"└── droonga\n"
+"    └── plugins\n"
+"            └── delete-stores.rb\n"
+"~~~"
+msgstr ""
+
+msgid "lib/droonga/plugins/delete-stores.rb:"
 msgstr ""
 
 msgid ""
-"      class Handler < Droonga::Handler\n"
-"        message.type = \"add\" # This was \"search\" in the previous version."
+"module Droonga\n"
+"  module Plugins\n"
+"    module DeleteStoresPlugin\n"
+"      Plugin.registry.register(\"delete-stores\", self)\n"
+"    end\n"
+"  end\n"
+"end\n"
+"~~~"
 msgstr ""
 
-msgid "Restart `fluentd`:"
+msgid "Define a \"step\" for the new `deleteStores` command, in your plugin. Like:"
 msgstr ""
 
 msgid ""
-"~~~\n"
-"# kill $(cat fluentd.pid)\n"
-"# RUBYLIB=./lib fluentd --config fluentd.conf --log fluentd.log --daemon fluen"
-"td.pid\n"
+"module Droonga\n"
+"  module Plugins\n"
+"    module DeleteStoresPlugin\n"
+"      Plugin.registry.register(\"delete-stores\", self)"
+msgstr ""
+
+msgid ""
+"      define_single_step do |step|\n"
+"        step.name = \"deleteStores\"\n"
+"        step.write = true\n"
+"      end\n"
+"    end\n"
+"  end\n"
+"end\n"
 "~~~"
 msgstr ""
 
 msgid ""
-"Let's send a request to Droonga Engine.\n"
-"Here, we use the first line of `stores.json`."
+"Look at a new configuration `step.write`.\n"
+"Because this command modifies the storage, we must indicate it clearly."
 msgstr ""
 
-msgid "add-store.json:"
+msgid "Let's define the handler."
 msgstr ""
 
 msgid ""
-"~~~\n"
-"{\"dataset\":\"Starbucks\",\"type\":\"add\",\"body\":{\"table\":\"Store\",\"key\":\"1st Avenue "
-"& 75th St. - New York NY  (W)\",\"values\":{\"location\":\"40.770262,-73.954798\"}}}\n"
+"      define_single_step do |step|\n"
+"        step.name = \"deleteStores\"\n"
+"        step.write = true\n"
+"        step.handler = :Handler\n"
+"        step.collector = AndCollector\n"
+"      end"
+msgstr ""
+
+msgid ""
+"      class Handler < Droonga::Handler\n"
+"        def handle(message)\n"
+"          keyword = message[\"body\"][\"keyword\"]\n"
+"          table = @context[\"Store\"]\n"
+"          table.delete do |record|\n"
+"            record.key @ keyword\n"
+"          end\n"
+"          true\n"
+"        end\n"
+"      end\n"
+"    end\n"
+"  end\n"
+"end\n"
 "~~~"
 msgstr ""
 
-msgid "Send it to the engine:"
+msgid ""
+"The handler finds and deletes existing records which have the given keyword in"
+" its \"key\", by the [API of Rroonga][Groonga::Table_delete]."
+msgstr ""
+
+msgid ""
+"And, the `AndCollector` is bound to the step by the configuration `step.collec"
+"tor`.\n"
+"It is is also one of built-in collectors, and merges boolean values retuned fr"
+"om handler instances for each partition and replica, to one boolean value."
+msgstr ""
+
+msgid ""
+"Update catalog.json to activate this plugin.\n"
+"Add `\"delete-stores\"` to `\"plugins\"`."
 msgstr ""
 
 msgid ""
 "~~~\n"
-"# droonga-request --tag starbucks add-store.json\n"
+"(snip)\n"
+"      \"datasets\": {\n"
+"        \"Starbucks\": {\n"
+"          (snip)\n"
+"          \"plugins\": [\"delete-stores\", \"count-records\", \"groonga\", \"crud\", \"se"
+"arch\"],\n"
+"(snip)\n"
 "~~~"
 msgstr ""
 
-msgid "Instead, you will see results like this in `fluentd.log`:"
+msgid "Restart the Droonga Engine and send the request."
 msgstr ""
 
 msgid ""
 "~~~\n"
-"2014-02-17 16:29:18 +0900 [info]: Droonga::Plugins::SampleLoggerPlugin message"
-"=#<Droonga::HandlerMessage:0x007f7f6a66c4c0 @raw={\"dataset\"=>\"Starbucks\", \"typ"
-"e\"=>\"add\", \"body\"=>{\"id\"=>\"localhost:24224/starbucks.#2\", \"task\"=>{\"route\"=>\"l"
-"ocalhost:24224/starbucks.000\", \"step\"=>{\"command\"=>\"add\", \"dataset\"=>\"Starbuck"
-"s\", \"body\"=>{\"table\"=>\"Store\", \"key\"=>\"1st Avenue & 75th St. - New York NY  (W"
-")\", \"values\"=>{\"location\"=>\"40.770262,-73.954798\"}}, \"key\"=>\"1st Avenue & 75th"
-" St. - New York NY  (W)\", \"type\"=>\"scatter\", \"outputs\"=>[\"errors\", \"success\"],"
-" \"replica\"=>\"all\", \"post\"=>true, \"routes\"=>[\"localhost:24224/starbucks.000\", \""
-"localhost:24224/starbucks.001\"], \"n_of_expects\"=>0, \"descendants\"=>{\"errors\"=>"
-"[\"localhost:24224/starbucks.#2\"], \"success\"=>[\"localhost:24224/starbucks.#2\"]}"
-"}, \"n_of_inputs\"=>0, \"values\"=>{}}, \"descendants\"=>{\"errors\"=>[\"localhost:2422"
-"4/starbucks\"], \"success\"=>[\"localhost:24224/starbucks\"]}}, \"replyTo\"=>{\"type\"="
-">\"add.result\", \"to\"=>\"127.0.0.1:50480/droonga\"}, \"id\"=>\"1392622158.374441\", \"d"
-"ate\"=>\"2014-02-17 16:29:18 +0900\", \"appliedAdapters\"=>[\"Droonga::Plugins::CRUD"
-"::Adapter\", \"Droonga::Plugins::Error::Adapter\"]}, @body={\"id\"=>\"localhost:2422"
-"4/starbucks.#2\", \"task\"=>{\"route\"=>\"localhost:24224/starbucks.000\", \"step\"=>{\""
-"command\"=>\"add\", \"dataset\"=>\"Starbucks\", \"body\"=>{\"table\"=>\"Store\", \"key\"=>\"1s"
-"t Avenue & 75th St. - New York NY  (W)\", \"values\"=>{\"location\"=>\"40.770262,-73"
-".954798\"}}, \"key\"=>\"1st Avenue & 75th St. - New York NY  (W)\", \"type\"=>\"scatte"
-"r\", \"outputs\"=>[\"errors\", \"success\"], \"replica\"=>\"all\", \"post\"=>true, \"routes\""
-"=>[\"localhost:24224/starbucks.000\", \"localhost:24224/starbucks.001\"], \"n_of_ex"
-"pects\"=>0, \"descendants\"=>{\"errors\"=>[\"localhost:24224/starbucks.#2\"], \"succes"
-"s\"=>[\"localhost:24224/starbucks.#2\"]}}, \"n_of_inputs\"=>0, \"values\"=>{}}, \"desc"
-"endants\"=>{\"errors\"=>[\"localhost:24224/starbucks\"], \"success\"=>[\"localhost:242"
-"24/starbucks\"]}}, @task={\"route\"=>\"localhost:24224/starbucks.000\", \"step\"=>{\"c"
-"ommand\"=>\"add\", \"dataset\"=>\"Starbucks\", \"body\"=>{\"table\"=>\"Store\", \"key\"=>\"1st"
-" Avenue & 75th St. - New York NY  (W)\", \"values\"=>{\"location\"=>\"40.770262,-73."
-"954798\"}}, \"key\"=>\"1st Avenue & 75th St. - New York NY  (W)\", \"type\"=>\"scatter"
-"\", \"outputs\"=>[\"errors\", \"success\"], \"replica\"=>\"all\", \"post\"=>true, \"routes\"="
-">[\"localhost:24224/starbucks.000\", \"localhost:24224/starbucks.001\"], \"n_of_exp"
-"ects\"=>0, \"descendants\"=>{\"errors\"=>[\"localhost:24224/starbucks.#2\"], \"success"
-"\"=>[\"localhost:24224/starbucks.#2\"]}}, \"n_of_inputs\"=>0, \"values\"=>{}}, @step="
-"{\"command\"=>\"add\", \"dataset\"=>\"Starbucks\", \"body\"=>{\"table\"=>\"Store\", \"key\"=>\""
-"1st Avenue & 75th St. - New York NY  (W)\", \"values\"=>{\"location\"=>\"40.770262,-"
-"73.954798\"}}, \"key\"=>\"1st Avenue & 75th St. - New York NY  (W)\", \"type\"=>\"scat"
-"ter\", \"outputs\"=>[\"errors\", \"success\"], \"replica\"=>\"all\", \"post\"=>true, \"route"
-"s\"=>[\"localhost:24224/starbucks.000\", \"localhost:24224/starbucks.001\"], \"n_of_"
-"expects\"=>0, \"descendants\"=>{\"errors\"=>[\"localhost:24224/starbucks.#2\"], \"succ"
-"ess\"=>[\"localhost:24224/starbucks.#2\"]}}>\n"
-"2014-02-17 16:29:18 +0900 [info]: Droonga::Plugins::SampleLoggerPlugin message"
-"=#<Droonga::HandlerMessage:0x007f7f6a65ff40 @raw={\"dataset\"=>\"Starbucks\", \"typ"
-"e\"=>\"add\", \"body\"=>{\"id\"=>\"localhost:24224/starbucks.#2\", \"task\"=>{\"route\"=>\"l"
-"ocalhost:24224/starbucks.001\", \"step\"=>{\"command\"=>\"add\", \"dataset\"=>\"Starbuck"
-"s\", \"body\"=>{\"table\"=>\"Store\", \"key\"=>\"1st Avenue & 75th St. - New York NY  (W"
-")\", \"values\"=>{\"location\"=>\"40.770262,-73.954798\"}}, \"key\"=>\"1st Avenue & 75th"
-" St. - New York NY  (W)\", \"type\"=>\"scatter\", \"outputs\"=>[\"errors\", \"success\"],"
-" \"replica\"=>\"all\", \"post\"=>true, \"routes\"=>[\"localhost:24224/starbucks.000\", \""
-"localhost:24224/starbucks.001\"], \"n_of_expects\"=>0, \"descendants\"=>{\"errors\"=>"
-"[\"localhost:24224/starbucks.#2\"], \"success\"=>[\"localhost:24224/starbucks.#2\"]}"
-"}, \"n_of_inputs\"=>0, \"values\"=>{}}, \"descendants\"=>{\"errors\"=>[\"localhost:2422"
-"4/starbucks\"], \"success\"=>[\"localhost:24224/starbucks\"]}}, \"replyTo\"=>{\"type\"="
-">\"add.result\", \"to\"=>\"127.0.0.1:50480/droonga\"}, \"id\"=>\"1392622158.374441\", \"d"
-"ate\"=>\"2014-02-17 16:29:18 +0900\", \"appliedAdapters\"=>[\"Droonga::Plugins::CRUD"
-"::Adapter\", \"Droonga::Plugins::Error::Adapter\"]}, @body={\"id\"=>\"localhost:2422"
-"4/starbucks.#2\", \"task\"=>{\"route\"=>\"localhost:24224/starbucks.001\", \"step\"=>{\""
-"command\"=>\"add\", \"dataset\"=>\"Starbucks\", \"body\"=>{\"table\"=>\"Store\", \"key\"=>\"1s"
-"t Avenue & 75th St. - New York NY  (W)\", \"values\"=>{\"location\"=>\"40.770262,-73"
-".954798\"}}, \"key\"=>\"1st Avenue & 75th St. - New York NY  (W)\", \"type\"=>\"scatte"
-"r\", \"outputs\"=>[\"errors\", \"success\"], \"replica\"=>\"all\", \"post\"=>true, \"routes\""
-"=>[\"localhost:24224/starbucks.000\", \"localhost:24224/starbucks.001\"], \"n_of_ex"
-"pects\"=>0, \"descendants\"=>{\"errors\"=>[\"localhost:24224/starbucks.#2\"], \"succes"
-"s\"=>[\"localhost:24224/starbucks.#2\"]}}, \"n_of_inputs\"=>0, \"values\"=>{}}, \"desc"
-"endants\"=>{\"errors\"=>[\"localhost:24224/starbucks\"], \"success\"=>[\"localhost:242"
-"24/starbucks\"]}}, @task={\"route\"=>\"localhost:24224/starbucks.001\", \"step\"=>{\"c"
-"ommand\"=>\"add\", \"dataset\"=>\"Starbucks\", \"body\"=>{\"table\"=>\"Store\", \"key\"=>\"1st"
-" Avenue & 75th St. - New York NY  (W)\", \"values\"=>{\"location\"=>\"40.770262,-73."
-"954798\"}}, \"key\"=>\"1st Avenue & 75th St. - New York NY  (W)\", \"type\"=>\"scatter"
-"\", \"outputs\"=>[\"errors\", \"success\"], \"replica\"=>\"all\", \"post\"=>true, \"routes\"="
-">[\"localhost:24224/starbucks.000\", \"localhost:24224/starbucks.001\"], \"n_of_exp"
-"ects\"=>0, \"descendants\"=>{\"errors\"=>[\"localhost:24224/starbucks.#2\"], \"success"
-"\"=>[\"localhost:24224/starbucks.#2\"]}}, \"n_of_inputs\"=>0, \"values\"=>{}}, @step="
-"{\"command\"=>\"add\", \"dataset\"=>\"Starbucks\", \"body\"=>{\"table\"=>\"Store\", \"key\"=>\""
-"1st Avenue & 75th St. - New York NY  (W)\", \"values\"=>{\"location\"=>\"40.770262,-"
-"73.954798\"}}, \"key\"=>\"1st Avenue & 75th St. - New York NY  (W)\", \"type\"=>\"scat"
-"ter\", \"outputs\"=>[\"errors\", \"success\"], \"replica\"=>\"all\", \"post\"=>true, \"route"
-"s\"=>[\"localhost:24224/starbucks.000\", \"localhost:24224/starbucks.001\"], \"n_of_"
-"expects\"=>0, \"descendants\"=>{\"errors\"=>[\"localhost:24224/starbucks.#2\"], \"succ"
-"ess\"=>[\"localhost:24224/starbucks.#2\"]}}>\n"
+"# kill $(cat fluentd.pid)\n"
+"# RUBYLIB=./lib fluentd --config fluentd.conf --log fluentd.log --daemon fluen"
+"td.pid\n"
+"# droonga-request --tag starbucks count-records.json\n"
+"Elapsed time: 0.01494\n"
+"[\n"
+"  \"droonga.message\",\n"
+"  1392621168,\n"
+"  {\n"
+"    \"inReplyTo\": \"1392621168.0119512\",\n"
+"    \"statusCode\": 200,\n"
+"    \"type\": \"deleteStores.result\",\n"
+"    \"body\": true\n"
+"  }\n"
+"]\n"
 "~~~"
 msgstr ""
 
 msgid ""
-"In `add` case, two log lines are shown for one request. This is because we hav"
-"e configured to have two replicas for each partition."
+"Because results from partitions are unified to just one boolean value, the res"
+"ponse's `body` is a `true`.\n"
+"As the verification, send the request of `countRecords` command."
+msgstr ""
+
+msgid ""
+"~~~\n"
+"# droonga-request --tag starbucks count-records.json\n"
+"Elapsed time: 0.01494\n"
+"[\n"
+"  \"droonga.message\",\n"
+"  1392621168,\n"
+"  {\n"
+"    \"inReplyTo\": \"1392621168.0119512\",\n"
+"    \"statusCode\": 200,\n"
+"    \"type\": \"countRecords.result\",\n"
+"    \"body\": [8, 8, 7]\n"
+"  }\n"
+"]\n"
+"~~~"
 msgstr ""
 
 msgid ""
-"In order to be consistent, `add` command must reach all of the replicas of the"
-" partition, but not the other partitions.\n"
-"As a consequence, `localhost:24224/starbucks.000` and `localhost:24224/starbuc"
-"ks.001` are chosen."
+"Note, the number of records are smaller than the previous result.\n"
+"This means that 4 or some records are deleted from each partitions."
 msgstr ""
 
 msgid "## Conclusion"
@@ -504,5 +662,8 @@ msgstr ""
 
 msgid ""
 "  [adapter]: ../adapter\n"
-"  [basic]: ../basic"
+"  [basic]: ../basic\n"
+"  [Groonga::Context]: http://ranguba.org/rroonga/en/Groonga/Context.html\n"
+"  [Groonga::Table_delete]: http://ranguba.org/rroonga/en/Groonga/Table.html#de"
+"lete-instance_method"
 msgstr ""

  Modified: _po/ja/tutorial/plugin-development/index.po (+2 -2)
===================================================================
--- _po/ja/tutorial/plugin-development/index.po    2014-02-28 12:11:33 +0900 (72b84ed)
+++ _po/ja/tutorial/plugin-development/index.po    2014-02-28 12:16:16 +0900 (12d4f24)
@@ -60,7 +60,7 @@ msgid ""
 msgstr ""
 
 msgid "You can use plugins in those situations."
-msgstr "このような状況でプラグインを利用することができます。"
+msgstr ""
 
 msgid "## Pluggable operations in Droonga Engine"
 msgstr "## Droongaエンジンにおけるプラガブルな操作"
@@ -116,7 +116,7 @@ msgid "## How to develop plugins?"
 msgstr "## プラグインを開発するには"
 
 msgid "For more details, let's read these sub tutorials:"
-msgstr "詳細は以下のサブチュートリアルを参照してください:"
+msgstr ""
 
 msgid ""
 " 1. [Modify requests and responses][adapter]\n"

  Modified: ja/tutorial/plugin-development/adapter/index.md (+1 -1)
===================================================================
--- ja/tutorial/plugin-development/adapter/index.md    2014-02-28 12:11:33 +0900 (3c15cf9)
+++ ja/tutorial/plugin-development/adapter/index.md    2014-02-28 12:16:16 +0900 (9f5a856)
@@ -19,7 +19,7 @@ layout: ja
 
 Learning steps to develop a Droonga plugin by yourself.
 
-This page focuses at the adaption phase for Droonga plugins.
+This page focuses on the adaption phase for Droonga plugins.
 At the last, wraps up them to make a small practical plugin named `store-search`, for the adaption phase.
 
 ## 前提条件

  Modified: ja/tutorial/plugin-development/index.md (+2 -2)
===================================================================
--- ja/tutorial/plugin-development/index.md    2014-02-28 12:11:33 +0900 (7c78935)
+++ ja/tutorial/plugin-development/index.md    2014-02-28 12:16:16 +0900 (a33f053)
@@ -32,7 +32,7 @@ Generally, data processing tasks in the real world need custom treatments of the
  * One may want to do more complex data processing than that provided by Droonga as built-in, to have direct storage access for efficiency.
  * One may need to control data distribution and collection logic of Droonga to profit from distributed nature of Droonga.
 
-このような状況でプラグインを利用することができます。
+You can use plugins in those situations.
 
 ## Droongaエンジンにおけるプラガブルな操作
 
@@ -64,7 +64,7 @@ Following this tutorial, you will learn how to write plugins. This will be the f
 
 ## プラグインを開発するには
 
-詳細は以下のサブチュートリアルを参照してください:
+For more details, let's read these sub tutorials:
 
  1. [Modify requests and responses][adapter]
  2. [Handle requests on all partitions][handler]
-------------- next part --------------
HTML����������������������������...
Download 



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