droonga-engine 1.0.7 → 1.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +2 -2
  3. data/bin/droonga-engine-absorb-data +200 -86
  4. data/bin/droonga-engine-configure +14 -11
  5. data/bin/droonga-engine-join +178 -59
  6. data/droonga-engine.gemspec +1 -1
  7. data/install.sh +1 -0
  8. data/lib/droonga/buffered_tcp_socket.rb +2 -2
  9. data/lib/droonga/catalog/base.rb +18 -0
  10. data/lib/droonga/catalog/dataset.rb +8 -0
  11. data/lib/droonga/catalog/version1.rb +3 -12
  12. data/lib/droonga/catalog/version2.rb +5 -12
  13. data/lib/droonga/command/droonga_engine.rb +6 -61
  14. data/lib/droonga/command/droonga_engine_service.rb +1 -0
  15. data/lib/droonga/command/droonga_engine_worker.rb +1 -0
  16. data/lib/droonga/command/remote.rb +18 -1
  17. data/lib/droonga/command/serf_event_handler.rb +3 -0
  18. data/lib/droonga/data_absorber.rb +234 -44
  19. data/lib/droonga/distributed_command_planner.rb +5 -5
  20. data/lib/droonga/engine.rb +27 -15
  21. data/lib/droonga/engine/version.rb +1 -1
  22. data/lib/droonga/handler_runner.rb +4 -0
  23. data/lib/droonga/node_status.rb +6 -2
  24. data/lib/droonga/path.rb +8 -14
  25. data/lib/droonga/planner.rb +4 -3
  26. data/lib/droonga/plugin/metadata/handler_action.rb +8 -0
  27. data/lib/droonga/plugins/groonga/column_create.rb +1 -1
  28. data/lib/droonga/plugins/groonga/column_list.rb +23 -1
  29. data/lib/droonga/plugins/groonga/column_remove.rb +1 -1
  30. data/lib/droonga/plugins/groonga/column_rename.rb +1 -1
  31. data/lib/droonga/plugins/groonga/delete.rb +1 -1
  32. data/lib/droonga/plugins/groonga/select.rb +17 -2
  33. data/lib/droonga/plugins/groonga/table_create.rb +26 -1
  34. data/lib/droonga/plugins/groonga/table_remove.rb +1 -1
  35. data/lib/droonga/plugins/search.rb +1 -1
  36. data/lib/droonga/plugins/search/distributed_search_planner.rb +15 -7
  37. data/lib/droonga/processor.rb +3 -2
  38. data/lib/droonga/searcher.rb +31 -15
  39. data/lib/droonga/serf.rb +1 -0
  40. data/lib/droonga/service_installation.rb +2 -2
  41. data/lib/droonga/single_step.rb +2 -2
  42. data/test/command/fixture/event.jsons +3 -2
  43. data/test/command/fixture/user-table.jsons +3 -2
  44. data/test/command/fixture/users.jsons +25 -0
  45. data/test/command/run-test.rb +13 -1
  46. data/test/command/suite/groonga/column_create/scalar.test +3 -2
  47. data/test/command/suite/groonga/column_create/vector.test +3 -2
  48. data/test/command/suite/groonga/column_list/{success.expected → no-key.expected} +0 -0
  49. data/test/command/suite/groonga/column_list/{success.test → no-key.test} +1 -1
  50. data/test/command/suite/groonga/column_list/with-key.expected +96 -0
  51. data/test/command/suite/groonga/column_list/with-key.test +25 -0
  52. data/test/command/suite/groonga/column_remove/success.test +3 -2
  53. data/test/command/suite/groonga/column_remove/unknown-column.test +3 -2
  54. data/test/command/suite/groonga/column_rename/success.test +3 -2
  55. data/test/command/suite/groonga/column_rename/unknown-column.test +3 -2
  56. data/test/command/suite/groonga/delete/duplicated-identifiers.test +3 -2
  57. data/test/command/suite/groonga/delete/no-identifier.test +3 -2
  58. data/test/command/suite/groonga/select/output_columns/default/array.expected +33 -0
  59. data/test/command/suite/groonga/select/output_columns/default/array.test +38 -0
  60. data/test/command/suite/groonga/select/output_columns/nonexistent.expected +28 -0
  61. data/test/command/suite/groonga/select/output_columns/nonexistent.test +26 -0
  62. data/test/command/suite/groonga/table_create/dat-without-key-type.expected +14 -0
  63. data/test/command/suite/groonga/table_create/dat-without-key-type.test +8 -0
  64. data/test/command/suite/groonga/table_create/dat.expected +13 -0
  65. data/test/command/suite/groonga/table_create/dat.test +9 -0
  66. data/test/command/suite/groonga/table_create/hash-without-key-type.expected +14 -0
  67. data/test/command/suite/groonga/table_create/hash-without-key-type.test +8 -0
  68. data/test/command/suite/groonga/table_create/hash.test +3 -2
  69. data/test/command/suite/groonga/table_create/pat-without-key-type.expected +14 -0
  70. data/test/command/suite/groonga/table_create/pat-without-key-type.test +8 -0
  71. data/test/command/suite/groonga/table_create/pat.expected +13 -0
  72. data/test/command/suite/groonga/table_create/pat.test +9 -0
  73. data/test/command/suite/groonga/table_list/success.test +3 -2
  74. data/test/unit/catalog/test_version1.rb +2 -2
  75. data/test/unit/catalog/test_version2.rb +3 -3
  76. data/test/unit/helper.rb +2 -2
  77. data/test/unit/helper/distributed_search_planner_helper.rb +9 -1
  78. data/test/unit/plugins/groonga/select/test_adapter_input.rb +15 -2
  79. data/test/unit/plugins/groonga/test_column_list.rb +119 -4
  80. data/test/unit/plugins/groonga/test_table_create.rb +29 -0
  81. data/test/unit/plugins/search/planner/test_basic.rb +2 -2
  82. data/test/unit/plugins/search/test_planner.rb +10 -2
  83. metadata +43 -8
@@ -37,7 +37,7 @@ module Droonga
37
37
  end
38
38
 
39
39
  class Handler < Droonga::Handler
40
- action.synchronous = true
40
+ action.change_schema = true
41
41
 
42
42
  def handle(message)
43
43
  command = Command.new(@context)
@@ -25,7 +25,7 @@ module Droonga
25
25
 
26
26
  class Planner < Droonga::Planner
27
27
  def plan(message)
28
- planner = DistributedSearchPlanner.new(message)
28
+ planner = DistributedSearchPlanner.new(@dataset, message)
29
29
  planner.plan
30
30
  end
31
31
  end
@@ -22,7 +22,7 @@ module Droonga
22
22
  module Plugins
23
23
  module Search
24
24
  class DistributedSearchPlanner < DistributedCommandPlanner
25
- def initialize(search_request_message)
25
+ def initialize(dataset, search_request_message)
26
26
  super
27
27
 
28
28
  @request = @source_message["body"]
@@ -43,7 +43,6 @@ module Droonga
43
43
  transform_query(input_name, query)
44
44
  end
45
45
 
46
- @dataset = @source_message["dataset"] || @request["dataset"]
47
46
  broadcast(:body => @request)
48
47
 
49
48
  super
@@ -79,7 +78,7 @@ module Droonga
79
78
  def transform_query(input_name, query)
80
79
  return unless need_reduce?(query)
81
80
 
82
- transformer = QueryTransformer.new(query)
81
+ transformer = QueryTransformer.new(@dataset, query)
83
82
  elements = transformer.mappers
84
83
  mapper = {}
85
84
  mapper["elements"] = elements unless elements.empty?
@@ -103,7 +102,8 @@ module Droonga
103
102
  class QueryTransformer
104
103
  attr_reader :reducers, :mappers
105
104
 
106
- def initialize(query)
105
+ def initialize(dataset, query)
106
+ @dataset = dataset
107
107
  @query = query
108
108
  @output = @query["output"]
109
109
  @reducers = {}
@@ -210,10 +210,14 @@ module Droonga
210
210
  end
211
211
 
212
212
  def final_offset
213
+ return @original_output_offset if @dataset.single_slice?
214
+
213
215
  @original_sort_offset + @original_output_offset
214
216
  end
215
217
 
216
218
  def final_limit
219
+ return @original_output_limit if @dataset.single_slice?
220
+
217
221
  if @original_sort_limit == UNLIMITED and
218
222
  @original_output_limit == UNLIMITED
219
223
  UNLIMITED
@@ -247,13 +251,17 @@ module Droonga
247
251
  "type" => "sum",
248
252
  }
249
253
  if unifiable?
250
- @query["sortBy"]["limit"] = -1 if @query["sortBy"].is_a?(Hash)
251
- @output["limit"] = -1
254
+ unless @dataset.single_slice?
255
+ if @query["sortBy"].is_a?(Hash)
256
+ @query["sortBy"]["limit"] = UNLIMITED
257
+ end
258
+ @output["limit"] = UNLIMITED
259
+ end
252
260
  mapper = {
253
261
  "target" => "records",
254
262
  }
255
263
  unless @output["elements"].include?("records")
256
- @records_limit = -1
264
+ @records_limit = UNLIMITED unless @dataset.single_slice?
257
265
  @output["elements"] << "records"
258
266
  @output["attributes"] ||= ["_key"]
259
267
  @output_records = false
@@ -44,9 +44,10 @@ module Droonga
44
44
  if @handler_runner.processable?(type)
45
45
  logger.trace("process: handlable: #{type}")
46
46
  synchronous = @handler_runner.prefer_synchronous?(type)
47
- if @n_workers.zero? or synchronous
47
+ change_schema = @handler_runner.change_schema?(type)
48
+ if @n_workers.zero? or synchronous or change_schema
48
49
  @handler_runner.process(message)
49
- if synchronous
50
+ if change_schema
50
51
  @job_pusher.broadcast(database_reopen_message)
51
52
  end
52
53
  else
@@ -462,14 +462,16 @@ module Droonga
462
462
  sub_record_table = table.range
463
463
  sub_attributes = format(attribute[:attributes], sub_record_table)
464
464
 
465
- format_attribute_subrecs(label, sub_attributes)
465
+ yield(format_attribute_subrecs(label, sub_attributes))
466
466
  else
467
467
  expression = attribute[:expression]
468
468
  if expression
469
- format_attribute_expression(label, expression)
469
+ yield(format_attribute_expression(label, expression))
470
470
  else
471
471
  column = table.column(source)
472
- format_attribute_column(label, column)
472
+ if column
473
+ yield(format_attribute_column(label, column))
474
+ end
473
475
  end
474
476
  end
475
477
  end
@@ -495,9 +497,13 @@ module Droonga
495
497
  end
496
498
 
497
499
  def format(attributes, table)
498
- attributes.collect do |attribute|
499
- format_attribute(attribute, table)
500
+ formatted_attributes = []
501
+ attributes.each do |attribute|
502
+ format_attribute(attribute, table) do |formatted_attribute|
503
+ formatted_attributes << formatted_attribute
504
+ end
500
505
  end
506
+ formatted_attributes
501
507
  end
502
508
  end
503
509
 
@@ -522,9 +528,10 @@ module Droonga
522
528
  def format(attributes, table)
523
529
  formatted_attributes = {}
524
530
  attributes.each do |attribute|
525
- formatted_attribute = format_attribute(attribute, table)
526
- attribute_name = attribute[:label]
527
- formatted_attributes[attribute_name] = formatted_attribute
531
+ format_attribute(attribute, table) do |formatted_attribute|
532
+ attribute_name = attribute[:label]
533
+ formatted_attributes[attribute_name] = formatted_attribute
534
+ end
528
535
  end
529
536
  formatted_attributes
530
537
  end
@@ -547,25 +554,28 @@ module Droonga
547
554
 
548
555
  private
549
556
  def record_value(record, attribute)
550
- if attribute[:source] == "_subrecs"
557
+ source = attribute[:source]
558
+ if source == "_subrecs"
551
559
  if record.table.is_a?(Groonga::Array)
552
560
  target_record = record.value
553
561
  else
554
562
  target_record = record
555
563
  end
556
- target_record.sub_records.collect do |sub_record|
564
+ values = target_record.sub_records.collect do |sub_record|
557
565
  sub_attributes = attribute[:attributes]
558
566
  format_record(sub_attributes, sub_record)
559
567
  end
568
+ yield(values)
560
569
  else
561
570
  expression = attribute[:expression]
562
571
  if expression
563
572
  variable = attribute[:variable]
564
573
  variable.value = record
565
- expression.execute
574
+ yield(expression.execute)
566
575
  else
567
- column_value = record[attribute[:source]]
568
- format_column_value(column_value)
576
+ return unless record.have_column?(source)
577
+ column_value = record[source]
578
+ yield(format_column_value(column_value))
569
579
  end
570
580
  end
571
581
  end
@@ -589,9 +599,13 @@ module Droonga
589
599
 
590
600
  private
591
601
  def format_record(attributes, record)
602
+ formatted_record = []
592
603
  attributes.collect do |attribute|
593
- record_value(record, attribute)
604
+ record_value(record, attribute) do |formatted_value|
605
+ formatted_record << formatted_value
606
+ end
594
607
  end
608
+ formatted_record
595
609
  end
596
610
  end
597
611
 
@@ -602,7 +616,9 @@ module Droonga
602
616
  def format_record(attributes, record)
603
617
  values = {}
604
618
  attributes.each do |attribute|
605
- values[attribute[:label]] = record_value(record, attribute)
619
+ record_value(record, attribute) do |formatted_value|
620
+ values[attribute[:label]] = formatted_value
621
+ end
606
622
  end
607
623
  values
608
624
  end
data/lib/droonga/serf.rb CHANGED
@@ -70,6 +70,7 @@ module Droonga
70
70
  "-bind", "#{extract_host(@name)}:#{port}",
71
71
  "-event-handler", "droonga-engine-serf-event-handler",
72
72
  "-log-level", log_level,
73
+ "-tag", "role=engine",
73
74
  *retry_joins)
74
75
  logger.trace("start: done")
75
76
  end
@@ -75,13 +75,13 @@ module Droonga
75
75
 
76
76
  def installed_as_service?
77
77
  return false unless user_exist?
78
-
78
+
79
79
  #TODO: we should support systemd also...
80
80
  succeeded = system("service", "droonga-engine", "status",
81
81
  :out => "/dev/null",
82
82
  :err => "/dev/null")
83
83
  return true if succeeded
84
-
84
+
85
85
  #TODO: we should support systemd also...
86
86
  result = `service droonga-engine status`
87
87
  result.include?("running") or \
@@ -26,12 +26,12 @@ module Droonga
26
26
  def plan(message)
27
27
  if message["type"] == "search"
28
28
  # XXX: workaround
29
- planner = Plugins::Search::Planner.new
29
+ planner = Plugins::Search::Planner.new(@dataset)
30
30
  return planner.plan(message)
31
31
  end
32
32
 
33
33
  # XXX: Re-implement me.
34
- planner = Planner.new
34
+ planner = Planner.new(@dataset)
35
35
  options = {}
36
36
  options[:write] = @definition.write?
37
37
  collector_class = @definition.collector_class
@@ -3,8 +3,9 @@
3
3
  "type": "table_create",
4
4
  "dataset": "Default",
5
5
  "body": {
6
- "name" : "Event",
7
- "flags" : "TABLE_HASH_KEY"
6
+ "name" : "Event",
7
+ "flags" : "TABLE_HASH_KEY",
8
+ "key_type" : "ShortText"
8
9
  }
9
10
  }
10
11
  {
@@ -3,8 +3,9 @@
3
3
  "type": "table_create",
4
4
  "dataset": "Default",
5
5
  "body": {
6
- "name" : "User",
7
- "flags" : "TABLE_PAT_KEY"
6
+ "name" : "User",
7
+ "flags" : "TABLE_PAT_KEY",
8
+ "key_type" : "ShortText"
8
9
  }
9
10
  }
10
11
  {
@@ -0,0 +1,25 @@
1
+ #@include fixture/user-table.jsons
2
+ #@disable-logging
3
+ {
4
+ "dataset": "Default",
5
+ "type": "add",
6
+ "body": {
7
+ "table": "User",
8
+ "key": "Alice",
9
+ "values": {
10
+ "name": "Alice"
11
+ }
12
+ }
13
+ }
14
+ {
15
+ "dataset": "Default",
16
+ "type": "add",
17
+ "body": {
18
+ "table": "User",
19
+ "key": "Bob",
20
+ "values": {
21
+ "name": "Bob"
22
+ }
23
+ }
24
+ }
25
+ #@enable-logging
@@ -18,6 +18,19 @@
18
18
  require "rbconfig"
19
19
  require "fileutils"
20
20
 
21
+ def system_serf_exist?
22
+ system("serf", "version",
23
+ :out => "/dev/null",
24
+ :err => "/dev/null")
25
+ end
26
+
27
+ unless system_serf_exist?
28
+ puts("Serf is not installed to your system.")
29
+ puts("Install Serf before running this test.")
30
+ puts("See: http://www.serfdom.io/")
31
+ exit(false)
32
+ end
33
+
21
34
  def run(*command_line)
22
35
  return if system(*command_line)
23
36
  puts("failed to run: #{command_line.join(' ')}")
@@ -29,7 +42,6 @@ lib_dir = File.expand_path(File.join(base_dir, "..", "..", "lib"))
29
42
 
30
43
  drntest_options = []
31
44
  drntest_options.concat(["--base-path", base_dir])
32
- drntest_options.concat(["--droonga-engine-options", "--no-orchestration"])
33
45
  drntest_options.concat(ARGV)
34
46
 
35
47
  run("bundle", "exec", "drntest", *drntest_options)
@@ -2,8 +2,9 @@
2
2
  "type": "table_create",
3
3
  "dataset": "Default",
4
4
  "body": {
5
- "name" : "User",
6
- "flags" : "TABLE_PAT_KEY"
5
+ "name" : "User",
6
+ "flags" : "TABLE_PAT_KEY",
7
+ "key_type" : "ShortText"
7
8
  }
8
9
  }
9
10
  {
@@ -2,8 +2,9 @@
2
2
  "type": "table_create",
3
3
  "dataset": "Default",
4
4
  "body": {
5
- "name" : "User",
6
- "flags" : "TABLE_PAT_KEY"
5
+ "name" : "User",
6
+ "flags" : "TABLE_PAT_KEY",
7
+ "key_type" : "ShortText"
7
8
  }
8
9
  }
9
10
  {
@@ -3,7 +3,7 @@
3
3
  "dataset": "Default",
4
4
  "body": {
5
5
  "name" : "User",
6
- "flags" : "TABLE_PAT_KEY"
6
+ "flags" : "TABLE_NO_KEY"
7
7
  }
8
8
  }
9
9
  {
@@ -0,0 +1,96 @@
1
+ {
2
+ "inReplyTo": "request-id",
3
+ "statusCode": 200,
4
+ "type": "table_create.result",
5
+ "body": [
6
+ [
7
+ 0,
8
+ 0.0,
9
+ 0.0
10
+ ],
11
+ true
12
+ ]
13
+ }
14
+ {
15
+ "inReplyTo": "request-id",
16
+ "statusCode": 200,
17
+ "type": "column_create.result",
18
+ "body": [
19
+ [
20
+ 0,
21
+ 0.0,
22
+ 0.0
23
+ ],
24
+ true
25
+ ]
26
+ }
27
+ {
28
+ "inReplyTo": "request-id",
29
+ "statusCode": 200,
30
+ "type": "column_list.result",
31
+ "body": [
32
+ [
33
+ 0,
34
+ 0.0,
35
+ 0.0
36
+ ],
37
+ [
38
+ [
39
+ [
40
+ "id",
41
+ "UInt32"
42
+ ],
43
+ [
44
+ "name",
45
+ "ShortText"
46
+ ],
47
+ [
48
+ "path",
49
+ "ShortText"
50
+ ],
51
+ [
52
+ "type",
53
+ "ShortText"
54
+ ],
55
+ [
56
+ "flags",
57
+ "ShortText"
58
+ ],
59
+ [
60
+ "domain",
61
+ "ShortText"
62
+ ],
63
+ [
64
+ "range",
65
+ "ShortText"
66
+ ],
67
+ [
68
+ "source",
69
+ "ShortText"
70
+ ]
71
+ ],
72
+ [
73
+ 256,
74
+ "_key",
75
+ "",
76
+ "",
77
+ "COLUMN_SCALAR",
78
+ "User",
79
+ "ShortText",
80
+ []
81
+ ],
82
+ [
83
+ 257,
84
+ "age",
85
+ "/path/to/column",
86
+ "fix",
87
+ "COLUMN_SCALAR",
88
+ "User",
89
+ "Int32",
90
+ [
91
+
92
+ ]
93
+ ]
94
+ ]
95
+ ]
96
+ }