droonga-engine 1.0.1

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 (341) hide show
  1. data/.dir-locals.el +3 -0
  2. data/.gitignore +6 -0
  3. data/.travis.yml +15 -0
  4. data/.yardopts +7 -0
  5. data/Gemfile +66 -0
  6. data/LICENSE.txt +14 -0
  7. data/README.md +17 -0
  8. data/Rakefile +64 -0
  9. data/benchmark/benchmark.rb +123 -0
  10. data/benchmark/utils.rb +246 -0
  11. data/benchmark/watch/benchmark-notify.rb +143 -0
  12. data/benchmark/watch/benchmark-notify.sh +20 -0
  13. data/benchmark/watch/benchmark-publish.rb +120 -0
  14. data/benchmark/watch/benchmark-scan.rb +213 -0
  15. data/bin/droonga-catalog-generate +103 -0
  16. data/bin/droonga-engine +20 -0
  17. data/bin/droonga-engine-service +20 -0
  18. data/doc/text/news.md +106 -0
  19. data/droonga-engine.gemspec +52 -0
  20. data/lib/droonga/adapter.rb +48 -0
  21. data/lib/droonga/adapter_runner.rb +104 -0
  22. data/lib/droonga/catalog/base.rb +41 -0
  23. data/lib/droonga/catalog/collection_volume.rb +106 -0
  24. data/lib/droonga/catalog/dataset.rb +69 -0
  25. data/lib/droonga/catalog/errors.rb +113 -0
  26. data/lib/droonga/catalog/schema.rb +186 -0
  27. data/lib/droonga/catalog/single_volume.rb +28 -0
  28. data/lib/droonga/catalog/slice.rb +41 -0
  29. data/lib/droonga/catalog/version1.rb +427 -0
  30. data/lib/droonga/catalog/version2.rb +96 -0
  31. data/lib/droonga/catalog/version2_validator.rb +63 -0
  32. data/lib/droonga/catalog/volume.rb +33 -0
  33. data/lib/droonga/catalog/volume_collection.rb +56 -0
  34. data/lib/droonga/catalog_generator.rb +156 -0
  35. data/lib/droonga/catalog_loader.rb +56 -0
  36. data/lib/droonga/catalog_observer.rb +83 -0
  37. data/lib/droonga/collector.rb +38 -0
  38. data/lib/droonga/collector_message.rb +71 -0
  39. data/lib/droonga/collector_runner.rb +64 -0
  40. data/lib/droonga/collectors/and.rb +26 -0
  41. data/lib/droonga/collectors/or.rb +26 -0
  42. data/lib/droonga/collectors/sum.rb +26 -0
  43. data/lib/droonga/collectors.rb +18 -0
  44. data/lib/droonga/dispatcher.rb +326 -0
  45. data/lib/droonga/distributed_command_planner.rb +179 -0
  46. data/lib/droonga/distributor.rb +87 -0
  47. data/lib/droonga/engine/command/droonga_engine.rb +441 -0
  48. data/lib/droonga/engine/version.rb +20 -0
  49. data/lib/droonga/engine.rb +80 -0
  50. data/lib/droonga/engine_state.rb +79 -0
  51. data/lib/droonga/error.rb +73 -0
  52. data/lib/droonga/error_messages.rb +33 -0
  53. data/lib/droonga/event_loop.rb +46 -0
  54. data/lib/droonga/farm.rb +58 -0
  55. data/lib/droonga/fluent_message_receiver.rb +191 -0
  56. data/lib/droonga/fluent_message_sender.rb +140 -0
  57. data/lib/droonga/forwarder.rb +119 -0
  58. data/lib/droonga/handler.rb +49 -0
  59. data/lib/droonga/handler_message.rb +61 -0
  60. data/lib/droonga/handler_messenger.rb +119 -0
  61. data/lib/droonga/handler_runner.rb +125 -0
  62. data/lib/droonga/input_message.rb +51 -0
  63. data/lib/droonga/job_protocol.rb +20 -0
  64. data/lib/droonga/job_pusher.rb +179 -0
  65. data/lib/droonga/job_receiver.rb +70 -0
  66. data/lib/droonga/loggable.rb +29 -0
  67. data/lib/droonga/logger.rb +142 -0
  68. data/lib/droonga/message_matcher.rb +109 -0
  69. data/lib/droonga/output_message.rb +55 -0
  70. data/lib/droonga/planner.rb +47 -0
  71. data/lib/droonga/pluggable.rb +31 -0
  72. data/lib/droonga/plugin/metadata/adapter_input_message.rb +39 -0
  73. data/lib/droonga/plugin/metadata/adapter_output_message.rb +39 -0
  74. data/lib/droonga/plugin/metadata/collector_message.rb +39 -0
  75. data/lib/droonga/plugin/metadata/handler_action.rb +39 -0
  76. data/lib/droonga/plugin/metadata/input_message.rb +54 -0
  77. data/lib/droonga/plugin.rb +43 -0
  78. data/lib/droonga/plugin_loader.rb +63 -0
  79. data/lib/droonga/plugin_registry.rb +66 -0
  80. data/lib/droonga/plugins/basic.rb +54 -0
  81. data/lib/droonga/plugins/crud.rb +145 -0
  82. data/lib/droonga/plugins/dump.rb +97 -0
  83. data/lib/droonga/plugins/error.rb +51 -0
  84. data/lib/droonga/plugins/groonga/column_create.rb +123 -0
  85. data/lib/droonga/plugins/groonga/column_list.rb +124 -0
  86. data/lib/droonga/plugins/groonga/column_remove.rb +65 -0
  87. data/lib/droonga/plugins/groonga/column_rename.rb +67 -0
  88. data/lib/droonga/plugins/groonga/delete.rb +117 -0
  89. data/lib/droonga/plugins/groonga/generic_command.rb +105 -0
  90. data/lib/droonga/plugins/groonga/generic_response.rb +43 -0
  91. data/lib/droonga/plugins/groonga/select.rb +236 -0
  92. data/lib/droonga/plugins/groonga/table_create.rb +111 -0
  93. data/lib/droonga/plugins/groonga/table_list.rb +120 -0
  94. data/lib/droonga/plugins/groonga/table_remove.rb +57 -0
  95. data/lib/droonga/plugins/groonga.rb +37 -0
  96. data/lib/droonga/plugins/search/distributed_search_planner.rb +407 -0
  97. data/lib/droonga/plugins/search.rb +146 -0
  98. data/lib/droonga/plugins/watch.rb +178 -0
  99. data/lib/droonga/processor.rb +63 -0
  100. data/lib/droonga/reducer.rb +169 -0
  101. data/lib/droonga/replier.rb +49 -0
  102. data/lib/droonga/schema_applier.rb +167 -0
  103. data/lib/droonga/searcher/mecab_filter.rb +67 -0
  104. data/lib/droonga/searcher.rb +733 -0
  105. data/lib/droonga/server.rb +45 -0
  106. data/lib/droonga/session.rb +99 -0
  107. data/lib/droonga/single_step.rb +68 -0
  108. data/lib/droonga/single_step_definition.rb +54 -0
  109. data/lib/droonga/slice.rb +122 -0
  110. data/lib/droonga/status_code.rb +25 -0
  111. data/lib/droonga/step_runner.rb +64 -0
  112. data/lib/droonga/sweeper.rb +42 -0
  113. data/lib/droonga/test/stub_handler.rb +37 -0
  114. data/lib/droonga/test/stub_handler_message.rb +35 -0
  115. data/lib/droonga/test/stub_handler_messenger.rb +34 -0
  116. data/lib/droonga/test/stub_planner.rb +31 -0
  117. data/lib/droonga/test.rb +21 -0
  118. data/lib/droonga/watch_schema.rb +92 -0
  119. data/lib/droonga/watcher.rb +257 -0
  120. data/lib/droonga/worker.rb +61 -0
  121. data/sample/cluster/catalog.json +42 -0
  122. data/sample/mecab_filter/data.grn +7 -0
  123. data/sample/mecab_filter/ddl.grn +7 -0
  124. data/sample/mecab_filter/search_with_mecab_filter.json +21 -0
  125. data/sample/mecab_filter/search_without_mecab_filter.json +21 -0
  126. data/test/command/config/default/catalog.json +85 -0
  127. data/test/command/config/default/fluentd.conf +11 -0
  128. data/test/command/config/version1/catalog.json +68 -0
  129. data/test/command/config/version1/fluentd.conf +11 -0
  130. data/test/command/fixture/documents.jsons +208 -0
  131. data/test/command/fixture/event.jsons +41 -0
  132. data/test/command/fixture/user-table-array.jsons +38 -0
  133. data/test/command/fixture/user-table.jsons +47 -0
  134. data/test/command/run-test.rb +34 -0
  135. data/test/command/suite/add/dimension/column.catalog.json +28 -0
  136. data/test/command/suite/add/dimension/column.expected +41 -0
  137. data/test/command/suite/add/dimension/column.test +51 -0
  138. data/test/command/suite/add/dimension/integer.catalog.json +19 -0
  139. data/test/command/suite/add/dimension/integer.expected +41 -0
  140. data/test/command/suite/add/dimension/integer.test +51 -0
  141. data/test/command/suite/add/error/invalid-integer.expected +46 -0
  142. data/test/command/suite/add/error/invalid-integer.test +12 -0
  143. data/test/command/suite/add/error/invalid-time.expected +46 -0
  144. data/test/command/suite/add/error/invalid-time.test +12 -0
  145. data/test/command/suite/add/error/missing-key.expected +25 -0
  146. data/test/command/suite/add/error/missing-key.test +16 -0
  147. data/test/command/suite/add/error/missing-table.expected +25 -0
  148. data/test/command/suite/add/error/missing-table.test +16 -0
  149. data/test/command/suite/add/error/unknown-column.expected +46 -0
  150. data/test/command/suite/add/error/unknown-column.test +12 -0
  151. data/test/command/suite/add/error/unknown-table.expected +25 -0
  152. data/test/command/suite/add/error/unknown-table.test +17 -0
  153. data/test/command/suite/add/minimum.expected +6 -0
  154. data/test/command/suite/add/minimum.test +11 -0
  155. data/test/command/suite/add/with-values.expected +6 -0
  156. data/test/command/suite/add/with-values.test +17 -0
  157. data/test/command/suite/add/without-key.expected +6 -0
  158. data/test/command/suite/add/without-key.test +16 -0
  159. data/test/command/suite/groonga/column_create/scalar.expected +26 -0
  160. data/test/command/suite/groonga/column_create/scalar.test +17 -0
  161. data/test/command/suite/groonga/column_create/unknown-table.expected +14 -0
  162. data/test/command/suite/groonga/column_create/unknown-table.test +7 -0
  163. data/test/command/suite/groonga/column_create/vector.expected +26 -0
  164. data/test/command/suite/groonga/column_create/vector.test +18 -0
  165. data/test/command/suite/groonga/column_list/success.expected +86 -0
  166. data/test/command/suite/groonga/column_list/success.test +24 -0
  167. data/test/command/suite/groonga/column_list/unknown-table.expected +13 -0
  168. data/test/command/suite/groonga/column_list/unknown-table.test +7 -0
  169. data/test/command/suite/groonga/column_remove/success.expected +39 -0
  170. data/test/command/suite/groonga/column_remove/success.test +25 -0
  171. data/test/command/suite/groonga/column_remove/unknown-column.expected +27 -0
  172. data/test/command/suite/groonga/column_remove/unknown-column.test +16 -0
  173. data/test/command/suite/groonga/column_remove/unknown-table.expected +14 -0
  174. data/test/command/suite/groonga/column_remove/unknown-table.test +7 -0
  175. data/test/command/suite/groonga/column_rename/success.expected +39 -0
  176. data/test/command/suite/groonga/column_rename/success.test +26 -0
  177. data/test/command/suite/groonga/column_rename/unknown-column.expected +27 -0
  178. data/test/command/suite/groonga/column_rename/unknown-column.test +16 -0
  179. data/test/command/suite/groonga/column_rename/unknown-table.expected +14 -0
  180. data/test/command/suite/groonga/column_rename/unknown-table.test +7 -0
  181. data/test/command/suite/groonga/delete/duplicated-identifiers.expected +27 -0
  182. data/test/command/suite/groonga/delete/duplicated-identifiers.test +17 -0
  183. data/test/command/suite/groonga/delete/filter.expected +19 -0
  184. data/test/command/suite/groonga/delete/filter.test +19 -0
  185. data/test/command/suite/groonga/delete/invalid-filter.expected +14 -0
  186. data/test/command/suite/groonga/delete/invalid-filter.test +9 -0
  187. data/test/command/suite/groonga/delete/no-identifier.expected +27 -0
  188. data/test/command/suite/groonga/delete/no-identifier.test +15 -0
  189. data/test/command/suite/groonga/delete/success.expected +19 -0
  190. data/test/command/suite/groonga/delete/success.test +19 -0
  191. data/test/command/suite/groonga/delete/unknown-table.expected +14 -0
  192. data/test/command/suite/groonga/delete/unknown-table.test +7 -0
  193. data/test/command/suite/groonga/select/minimum.expected +22 -0
  194. data/test/command/suite/groonga/select/minimum.test +8 -0
  195. data/test/command/suite/groonga/table_create/array.expected +14 -0
  196. data/test/command/suite/groonga/table_create/array.test +8 -0
  197. data/test/command/suite/groonga/table_create/hash.expected +13 -0
  198. data/test/command/suite/groonga/table_create/hash.test +8 -0
  199. data/test/command/suite/groonga/table_list/success.expected +71 -0
  200. data/test/command/suite/groonga/table_list/success.test +15 -0
  201. data/test/command/suite/groonga/table_remove/success.expected +13 -0
  202. data/test/command/suite/groonga/table_remove/success.test +8 -0
  203. data/test/command/suite/groonga/table_remove/unknown-table.expected +14 -0
  204. data/test/command/suite/groonga/table_remove/unknown-table.test +7 -0
  205. data/test/command/suite/message/error/missing-dataset.expected +9 -0
  206. data/test/command/suite/message/error/missing-dataset.test +5 -0
  207. data/test/command/suite/message/error/unknown-dataset.expected +9 -0
  208. data/test/command/suite/message/error/unknown-dataset.test +6 -0
  209. data/test/command/suite/message/error/unknown-type.expected +9 -0
  210. data/test/command/suite/message/error/unknown-type.test +6 -0
  211. data/test/command/suite/search/adjusters/multiple.catalog.json +38 -0
  212. data/test/command/suite/search/adjusters/multiple.expected +19 -0
  213. data/test/command/suite/search/adjusters/multiple.test +75 -0
  214. data/test/command/suite/search/adjusters/one.catalog.json +38 -0
  215. data/test/command/suite/search/adjusters/one.expected +19 -0
  216. data/test/command/suite/search/adjusters/one.test +66 -0
  217. data/test/command/suite/search/attributes/array.expected +21 -0
  218. data/test/command/suite/search/attributes/array.test +28 -0
  219. data/test/command/suite/search/attributes/hash.expected +30 -0
  220. data/test/command/suite/search/attributes/hash.test +36 -0
  221. data/test/command/suite/search/complex.expected +48 -0
  222. data/test/command/suite/search/complex.test +23 -0
  223. data/test/command/suite/search/condition/nested.expected +15 -0
  224. data/test/command/suite/search/condition/nested.test +27 -0
  225. data/test/command/suite/search/condition/query/nonexistent_column.catalog.json +37 -0
  226. data/test/command/suite/search/condition/query/nonexistent_column.expected +48 -0
  227. data/test/command/suite/search/condition/query/nonexistent_column.test +33 -0
  228. data/test/command/suite/search/condition/query/syntax_error.catalog.json +36 -0
  229. data/test/command/suite/search/condition/query/syntax_error.expected +48 -0
  230. data/test/command/suite/search/condition/query/syntax_error.test +33 -0
  231. data/test/command/suite/search/condition/query.expected +24 -0
  232. data/test/command/suite/search/condition/query.test +23 -0
  233. data/test/command/suite/search/condition/script.expected +24 -0
  234. data/test/command/suite/search/condition/script.test +26 -0
  235. data/test/command/suite/search/error/cyclic-source.expected +14 -0
  236. data/test/command/suite/search/error/cyclic-source.test +12 -0
  237. data/test/command/suite/search/error/deeply-cyclic-source.expected +17 -0
  238. data/test/command/suite/search/error/deeply-cyclic-source.test +15 -0
  239. data/test/command/suite/search/error/missing-source-parameter.expected +13 -0
  240. data/test/command/suite/search/error/missing-source-parameter.test +11 -0
  241. data/test/command/suite/search/error/no-query.expected +9 -0
  242. data/test/command/suite/search/error/no-query.test +7 -0
  243. data/test/command/suite/search/error/unknown-source.expected +52 -0
  244. data/test/command/suite/search/error/unknown-source.test +12 -0
  245. data/test/command/suite/search/group/count.expected +10 -0
  246. data/test/command/suite/search/group/count.test +18 -0
  247. data/test/command/suite/search/group/limit.expected +15 -0
  248. data/test/command/suite/search/group/limit.test +20 -0
  249. data/test/command/suite/search/group/string.expected +32 -0
  250. data/test/command/suite/search/group/string.test +40 -0
  251. data/test/command/suite/search/group/subrecord/with-sort.catalog.json +33 -0
  252. data/test/command/suite/search/group/subrecord/with-sort.expected +30 -0
  253. data/test/command/suite/search/group/subrecord/with-sort.test +81 -0
  254. data/test/command/suite/search/multiple/chained.expected +41 -0
  255. data/test/command/suite/search/multiple/chained.test +39 -0
  256. data/test/command/suite/search/multiple/parallel.expected +35 -0
  257. data/test/command/suite/search/multiple/parallel.test +35 -0
  258. data/test/command/suite/search/output/attributes/invalid.catalog.json +13 -0
  259. data/test/command/suite/search/output/attributes/invalid.expected +44 -0
  260. data/test/command/suite/search/output/attributes/invalid.test +28 -0
  261. data/test/command/suite/search/range/only-output.expected +24 -0
  262. data/test/command/suite/search/range/only-output.test +23 -0
  263. data/test/command/suite/search/range/only-sort.expected +24 -0
  264. data/test/command/suite/search/range/only-sort.test +26 -0
  265. data/test/command/suite/search/range/sort-and-output.expected +21 -0
  266. data/test/command/suite/search/range/sort-and-output.test +27 -0
  267. data/test/command/suite/search/range/too-large-output-offset.expected +12 -0
  268. data/test/command/suite/search/range/too-large-output-offset.test +23 -0
  269. data/test/command/suite/search/range/too-large-sort-offset.expected +12 -0
  270. data/test/command/suite/search/range/too-large-sort-offset.test +26 -0
  271. data/test/command/suite/search/response/elapsed_time.catalog.json +13 -0
  272. data/test/command/suite/search/response/elapsed_time.expected +11 -0
  273. data/test/command/suite/search/response/elapsed_time.test +26 -0
  274. data/test/command/suite/search/response/records/value/time.expected +20 -0
  275. data/test/command/suite/search/response/records/value/time.test +22 -0
  276. data/test/command/suite/search/simple.expected +48 -0
  277. data/test/command/suite/search/simple.test +22 -0
  278. data/test/command/suite/search/sort/default-offset-limit.expected +39 -0
  279. data/test/command/suite/search/sort/default-offset-limit.test +24 -0
  280. data/test/command/suite/search/sort/invisible-column.expected +24 -0
  281. data/test/command/suite/search/sort/invisible-column.test +26 -0
  282. data/test/command/suite/watch/subscribe.expected +6 -0
  283. data/test/command/suite/watch/subscribe.test +9 -0
  284. data/test/command/suite/watch/unsubscribe.expected +6 -0
  285. data/test/command/suite/watch/unsubscribe.test +9 -0
  286. data/test/performance/run-test.rb +56 -0
  287. data/test/performance/watch/catalog.json +33 -0
  288. data/test/performance/watch/feed.json +9 -0
  289. data/test/performance/watch/fluentd.conf +11 -0
  290. data/test/performance/watch/subscribe.json +3 -0
  291. data/test/unit/catalog/test_collection_volume.rb +103 -0
  292. data/test/unit/catalog/test_dataset.rb +104 -0
  293. data/test/unit/catalog/test_schema.rb +226 -0
  294. data/test/unit/catalog/test_single_volume.rb +31 -0
  295. data/test/unit/catalog/test_slice.rb +92 -0
  296. data/test/unit/catalog/test_version1.rb +361 -0
  297. data/test/unit/catalog/test_version2.rb +124 -0
  298. data/test/unit/catalog/test_version2_validator.rb +66 -0
  299. data/test/unit/catalog/test_volume_collection.rb +50 -0
  300. data/test/unit/fixtures/array.grn +18 -0
  301. data/test/unit/fixtures/catalog/version1.json +40 -0
  302. data/test/unit/fixtures/catalog/version2.json +62 -0
  303. data/test/unit/fixtures/document.grn +34 -0
  304. data/test/unit/fixtures/reference/array.grn +11 -0
  305. data/test/unit/fixtures/reference/hash.grn +7 -0
  306. data/test/unit/helper/distributed_search_planner_helper.rb +83 -0
  307. data/test/unit/helper/fixture.rb +28 -0
  308. data/test/unit/helper/plugin_helper.rb +38 -0
  309. data/test/unit/helper/sandbox.rb +86 -0
  310. data/test/unit/helper/stub_worker.rb +27 -0
  311. data/test/unit/helper/watch_helper.rb +23 -0
  312. data/test/unit/helper.rb +28 -0
  313. data/test/unit/plugins/crud/test_add.rb +190 -0
  314. data/test/unit/plugins/groonga/select/test_adapter_input.rb +510 -0
  315. data/test/unit/plugins/groonga/select/test_adapter_output.rb +201 -0
  316. data/test/unit/plugins/groonga/test_column_create.rb +171 -0
  317. data/test/unit/plugins/groonga/test_column_list.rb +170 -0
  318. data/test/unit/plugins/groonga/test_column_remove.rb +98 -0
  319. data/test/unit/plugins/groonga/test_column_rename.rb +105 -0
  320. data/test/unit/plugins/groonga/test_delete.rb +127 -0
  321. data/test/unit/plugins/groonga/test_table_create.rb +147 -0
  322. data/test/unit/plugins/groonga/test_table_list.rb +184 -0
  323. data/test/unit/plugins/groonga/test_table_remove.rb +61 -0
  324. data/test/unit/plugins/search/planner/test_basic.rb +120 -0
  325. data/test/unit/plugins/search/planner/test_group_by.rb +573 -0
  326. data/test/unit/plugins/search/planner/test_output.rb +388 -0
  327. data/test/unit/plugins/search/planner/test_sort_by.rb +938 -0
  328. data/test/unit/plugins/search/test_collector.rb +806 -0
  329. data/test/unit/plugins/search/test_handler.rb +930 -0
  330. data/test/unit/plugins/search/test_planner.rb +174 -0
  331. data/test/unit/plugins/test_basic.rb +510 -0
  332. data/test/unit/plugins/test_groonga.rb +70 -0
  333. data/test/unit/plugins/test_watch.rb +211 -0
  334. data/test/unit/run-test.rb +56 -0
  335. data/test/unit/test_catalog_generator.rb +93 -0
  336. data/test/unit/test_message_matcher.rb +160 -0
  337. data/test/unit/test_schema_applier.rb +59 -0
  338. data/test/unit/test_sweeper.rb +95 -0
  339. data/test/unit/test_watch_schema.rb +57 -0
  340. data/test/unit/test_watcher.rb +336 -0
  341. metadata +759 -0
@@ -0,0 +1,178 @@
1
+ # Copyright (C) 2013-2014 Droonga Project
2
+ #
3
+ # This library is free software; you can redistribute it and/or
4
+ # modify it under the terms of the GNU Lesser General Public
5
+ # License version 2.1 as published by the Free Software Foundation.
6
+ #
7
+ # This library is distributed in the hope that it will be useful,
8
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
9
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10
+ # Lesser General Public License for more details.
11
+ #
12
+ # You should have received a copy of the GNU Lesser General Public
13
+ # License along with this library; if not, write to the Free Software
14
+ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15
+
16
+ require "droonga/plugin"
17
+ require "droonga/watcher"
18
+ require "droonga/sweeper"
19
+ require "droonga/watch_schema"
20
+
21
+ module Droonga
22
+ module Plugins
23
+ module Watch
24
+ extend Plugin
25
+ register("watch")
26
+
27
+ module SchemaCreatable
28
+ private
29
+ def ensure_schema_created
30
+ # XXX just workaround. This must be re-written.
31
+ # When secondary and later processes opens the database,
32
+ # creation processes of tables by the first process is
33
+ # not finished yet. Then secondary and others tries to
34
+ # create tables and raises errors. To avoid such a problem,
35
+ # the creation processes of tables is disabled on workers.
36
+ if $0 !~ /\AServer/
37
+ schema = WatchSchema.new(@context)
38
+ schema.ensure_created
39
+ else
40
+ until @context["Keyword"]
41
+ sleep 0.1
42
+ end
43
+ sleep 1
44
+ end
45
+ end
46
+ end
47
+
48
+ module MessageParsable
49
+ private
50
+ def parse_message(message)
51
+ request = message.request
52
+ subscriber = request["subscriber"]
53
+ condition = request["condition"]
54
+ route = request["route"] || message["from"]
55
+ if condition
56
+ query = condition.to_json
57
+ else
58
+ query = nilondition
59
+ end
60
+ [subscriber, condition, query, route]
61
+ end
62
+ end
63
+
64
+ class SubscribeHandler < Droonga::Handler
65
+ include SchemaCreatable
66
+ include MessageParsable
67
+
68
+ def initialize(*args)
69
+ super
70
+ ensure_schema_created # TODO: REMOVE ME
71
+ end
72
+
73
+ def handle(message)
74
+ subscriber, condition, query, route = parse_message(message)
75
+ normalized_request = {
76
+ :subscriber => subscriber,
77
+ :condition => condition,
78
+ :query => query,
79
+ :route => route,
80
+ }
81
+ watcher = Watcher.new(@context)
82
+ watcher.subscribe(normalized_request)
83
+ true
84
+ end
85
+ end
86
+
87
+ define_single_step do |step|
88
+ step.name = "watch.subscribe"
89
+ step.write = true
90
+ step.handler = SubscribeHandler
91
+ step.collector = Collectors::And
92
+ end
93
+
94
+ class UnsubscribeHandler < Droonga::Handler
95
+ include SchemaCreatable
96
+ include MessageParsable
97
+
98
+ def initialize(*args)
99
+ super
100
+ ensure_schema_created # TODO: REMOVE ME
101
+ end
102
+
103
+ def handle(message)
104
+ subscriber, condition, query, route = parse_message(message)
105
+ _ = route # suppress a warning
106
+ normalized_request = {
107
+ :subscriber => subscriber,
108
+ :condition => condition,
109
+ :query => query,
110
+ }
111
+ watcher = Watcher.new(@context)
112
+ watcher.unsubscribe(normalized_request)
113
+ true
114
+ end
115
+ end
116
+
117
+ define_single_step do |step|
118
+ step.name = "watch.unsubscribe"
119
+ step.write = true
120
+ step.handler = UnsubscribeHandler
121
+ step.collector = Collectors::And
122
+ end
123
+
124
+ class FeedHandler < Droonga::Handler
125
+ include SchemaCreatable
126
+
127
+ def initialize(*args)
128
+ super
129
+ ensure_schema_created # TODO: REMOVE ME
130
+ end
131
+
132
+ def handle(message)
133
+ request = message.request
134
+ watcher = Watcher.new(@context)
135
+ watcher.feed(:targets => request["targets"]) do |route, subscribers|
136
+ published_message = {
137
+ "to" => subscribers,
138
+ "body" => request,
139
+ }
140
+ published_message = message.raw.merge(published_message)
141
+ messenger.forward(published_message,
142
+ "to" => route, "type" => "watch.publish")
143
+ end
144
+ nil
145
+ end
146
+ end
147
+
148
+ define_single_step do |step|
149
+ step.name = "watch.feed"
150
+ step.write = true
151
+ step.handler = FeedHandler
152
+ end
153
+
154
+ class SweepHandler < Droonga::Handler
155
+ include SchemaCreatable
156
+
157
+ message.type = "watch.sweep"
158
+
159
+ def initialize(*args)
160
+ super
161
+ ensure_schema_created # TODO: REMOVE ME
162
+ end
163
+
164
+ def handle(message)
165
+ sweeper = Sweeper.new(@context)
166
+ sweeper.sweep_expired_subscribers
167
+ nil
168
+ end
169
+ end
170
+
171
+ define_single_step do |step|
172
+ step.name = "watch.sweep"
173
+ step.write = true
174
+ step.handler = SweepHandler
175
+ end
176
+ end
177
+ end
178
+ end
@@ -0,0 +1,63 @@
1
+ # Copyright (C) 2013-2014 Droonga Project
2
+ #
3
+ # This library is free software; you can redistribute it and/or
4
+ # modify it under the terms of the GNU Lesser General Public
5
+ # License version 2.1 as published by the Free Software Foundation.
6
+ #
7
+ # This library is distributed in the hope that it will be useful,
8
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
9
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10
+ # Lesser General Public License for more details.
11
+ #
12
+ # You should have received a copy of the GNU Lesser General Public
13
+ # License along with this library; if not, write to the Free Software
14
+ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15
+
16
+ require "droonga/loggable"
17
+ require "droonga/handler_runner"
18
+
19
+ module Droonga
20
+ class Processor
21
+ include Loggable
22
+
23
+ def initialize(loop, job_pusher, options={})
24
+ @loop = loop
25
+ @job_pusher = job_pusher
26
+ @options = options
27
+ @n_workers = @options[:n_workers] || 0
28
+ end
29
+
30
+ def start
31
+ @handler_runner = HandlerRunner.new(@loop, @options)
32
+ @handler_runner.start
33
+ end
34
+
35
+ def shutdown
36
+ logger.trace("shutdown: start")
37
+ @handler_runner.shutdown
38
+ logger.trace("shutdown: done")
39
+ end
40
+
41
+ def process(message)
42
+ logger.trace("process: start")
43
+ type = message["type"]
44
+ if @handler_runner.processable?(type)
45
+ logger.trace("process: handlable: #{type}")
46
+ synchronous = @handler_runner.prefer_synchronous?(type)
47
+ if @n_workers.zero? or synchronous
48
+ @handler_runner.process(message)
49
+ else
50
+ @job_pusher.push(message)
51
+ end
52
+ else
53
+ logger.trace("process: ignore #{type}")
54
+ end
55
+ logger.trace("process: done")
56
+ end
57
+
58
+ private
59
+ def log_tag
60
+ "processor"
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,169 @@
1
+ # Copyright (C) 2014 Droonga Project
2
+ #
3
+ # This library is free software; you can redistribute it and/or
4
+ # modify it under the terms of the GNU Lesser General Public
5
+ # License version 2.1 as published by the Free Software Foundation.
6
+ #
7
+ # This library is distributed in the hope that it will be useful,
8
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
9
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10
+ # Lesser General Public License for more details.
11
+ #
12
+ # You should have received a copy of the GNU Lesser General Public
13
+ # License along with this library; if not, write to the Free Software
14
+ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15
+
16
+ module Droonga
17
+ class Reducer
18
+ class << self
19
+ # TODO: This is right location?
20
+ def apply_range(items, range)
21
+ if items and items.is_a?(Array)
22
+ offset = range["offset"] || 0
23
+ unless offset.zero?
24
+ items = items[offset..-1] || []
25
+ end
26
+
27
+ limit = range["limit"] || 0
28
+ unless limit == UNLIMITED
29
+ items = items[0...limit]
30
+ end
31
+ end
32
+ items
33
+ end
34
+ end
35
+
36
+ # XXX: We has ULIMITED defined
37
+ # lib/droonga/plugins/search/distributed_search_planner.rb. We
38
+ # should unify it.
39
+ UNLIMITED = -1
40
+
41
+ def initialize(deal)
42
+ @deal = deal # TODO: deal is good name?
43
+ end
44
+
45
+ def reduce(left_value, right_value)
46
+ if left_value.nil? or right_value.nil?
47
+ return right_value || left_value
48
+ end
49
+
50
+ reduced_value = nil
51
+
52
+ case @deal["type"]
53
+ when "and"
54
+ reduced_value = (left_value and right_value)
55
+ when "or"
56
+ reduced_value = (left_value or right_value)
57
+ when "sum"
58
+ reduced_value = sum(left_value, right_value)
59
+ reduced_value = self.class.apply_range(reduced_value,
60
+ "limit" => @deal["limit"])
61
+ when "average"
62
+ reduced_value = (left_value.to_f + right_value.to_f) / 2
63
+ when "sort"
64
+ reduced_value = merge(left_value,
65
+ right_value,
66
+ :operators => @deal["operators"],
67
+ :key_column => @deal["key_column"])
68
+ reduced_value = self.class.apply_range(reduced_value,
69
+ "limit" => @deal["limit"])
70
+ end
71
+
72
+ reduced_value
73
+ end
74
+
75
+ private
76
+ def sum(x, y)
77
+ return x || y if x.nil? or y.nil?
78
+
79
+ if x.is_a?(Hash) and y.is_a?(Hash)
80
+ x.merge(y)
81
+ else
82
+ x + y
83
+ end
84
+ end
85
+
86
+ def merge(x, y, options={})
87
+ operators = options[:operators] = normalize_operators(options[:operators])
88
+
89
+ unify_by_key!(x, y, options)
90
+
91
+ index = 0
92
+ y.each do |_y|
93
+ loop do
94
+ _x = x[index]
95
+ break unless _x
96
+ break if compare(_y, _x, operators)
97
+ index += 1
98
+ end
99
+ x.insert(index, _y)
100
+ index += 1
101
+ end
102
+ return x
103
+ end
104
+
105
+ def normalize_operators(operators)
106
+ operators ||= []
107
+ operators.collect do |operator|
108
+ if operator.is_a?(String)
109
+ { "operator" => operator }
110
+ else
111
+ operator
112
+ end
113
+ end
114
+ end
115
+
116
+ def compare(x, y, operators)
117
+ operators.each_with_index do |operator, index|
118
+ column = operator["column"] || index
119
+ operator = operator["operator"]
120
+ _x = x[column]
121
+ _y = y[column]
122
+ return true if _x.__send__(operator, _y)
123
+ end
124
+ return false
125
+ end
126
+
127
+ def unify_by_key!(base_items, unified_items, options={})
128
+ key_column_index = options[:key_column]
129
+ return unless key_column_index
130
+
131
+ # The unified records must be smaller than the base, because
132
+ # I sort unified records at last. I want to sort only smaller array.
133
+ if base_items.size < unified_items.size
134
+ base_items, unified_items = unified_items, base_items
135
+ end
136
+
137
+ unified_key_map = {}
138
+ unified_items.each do |unified_item|
139
+ unified_key_map[unified_item[key_column_index]] = unified_item
140
+ end
141
+
142
+ unified = false
143
+ base_items.reject! do |base_item|
144
+ key = base_item[key_column_index]
145
+ unified_item = unified_key_map[key]
146
+ if unified_item
147
+ base_item.each_with_index do |value, column_index|
148
+ next if column_index == key_column_index
149
+ unified_item[column_index] += value
150
+ end
151
+ unified = true
152
+ true
153
+ else
154
+ false
155
+ end
156
+ end
157
+
158
+ if unified
159
+ unified_items.sort! do |a, b|
160
+ if compare(a, b, options[:operators])
161
+ -1
162
+ else
163
+ 1
164
+ end
165
+ end
166
+ end
167
+ end
168
+ end
169
+ end
@@ -0,0 +1,49 @@
1
+ # Copyright (C) 2013 Droonga Project
2
+ #
3
+ # This library is free software; you can redistribute it and/or
4
+ # modify it under the terms of the GNU Lesser General Public
5
+ # License version 2.1 as published by the Free Software Foundation.
6
+ #
7
+ # This library is distributed in the hope that it will be useful,
8
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
9
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10
+ # Lesser General Public License for more details.
11
+ #
12
+ # You should have received a copy of the GNU Lesser General Public
13
+ # License along with this library; if not, write to the Free Software
14
+ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15
+
16
+ require "droonga/loggable"
17
+ require "droonga/status_code"
18
+
19
+ module Droonga
20
+ class Replier
21
+ include Loggable
22
+
23
+ def initialize(forwarder)
24
+ @forwarder = forwarder
25
+ end
26
+
27
+ def reply(message)
28
+ logger.trace("reply: start")
29
+ destination = message["replyTo"]
30
+ reply_message = {
31
+ "inReplyTo" => message["id"],
32
+ "statusCode" => message["statusCode"] || StatusCode::OK,
33
+ "type" => destination["type"],
34
+ "body" => message["body"],
35
+ }
36
+ if message.include?("errors")
37
+ errors = message["errors"]
38
+ reply_message["errors"] = errors unless errors.empty?
39
+ end
40
+ @forwarder.forward(reply_message, destination)
41
+ logger.trace("reply: done")
42
+ end
43
+
44
+ private
45
+ def log_tag
46
+ "[#{Process.ppid}][#{Process.pid}] replier"
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,167 @@
1
+ # Copyright (C) 2014 Droonga Project
2
+ #
3
+ # This library is free software; you can redistribute it and/or
4
+ # modify it under the terms of the GNU Lesser General Public
5
+ # License version 2.1 as published by the Free Software Foundation.
6
+ #
7
+ # This library is distributed in the hope that it will be useful,
8
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
9
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10
+ # Lesser General Public License for more details.
11
+ #
12
+ # You should have received a copy of the GNU Lesser General Public
13
+ # License along with this library; if not, write to the Free Software
14
+ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15
+
16
+ require "droonga/loggable"
17
+
18
+ module Droonga
19
+ class SchemaApplier
20
+ include Loggable
21
+
22
+ def initialize(context, schema)
23
+ @context = context
24
+ @schema = schema
25
+ end
26
+
27
+ def apply
28
+ # TODO: Support migration
29
+ Groonga::Schema.define(:context => @context) do |schema|
30
+ create_tables(schema)
31
+ create_reference_columns(schema)
32
+ create_index_columns(schema)
33
+ end
34
+ end
35
+
36
+ private
37
+ def each_table
38
+ reference_tables = []
39
+ @schema.tables.each_value do |table|
40
+ if reference_table?(table)
41
+ reference_tables << table
42
+ else
43
+ yield(table)
44
+ end
45
+ end
46
+ reference_tables.each do |table|
47
+ yield(table)
48
+ end
49
+ end
50
+
51
+ def reference_table?(table)
52
+ table.type != "Array" and !type_names.include?(table.key_type_groonga)
53
+ end
54
+
55
+ def each_column(table)
56
+ table.columns.each_value do |column|
57
+ yield(column)
58
+ end
59
+ end
60
+
61
+ def normal_column?(column)
62
+ column.type != "Index" and type_names.include?(column.value_type_groonga)
63
+ end
64
+
65
+ def reference_column?(column)
66
+ column.type != "Index" and !type_names.include?(column.value_type_groonga)
67
+ end
68
+
69
+ def index_column?(column)
70
+ column.type == "Index"
71
+ end
72
+
73
+ def types
74
+ @types ||= collect_available_types
75
+ end
76
+
77
+ def type_names
78
+ @type_names ||= types.collect(&:name)
79
+ end
80
+
81
+ def collect_available_types
82
+ each_options = {
83
+ :ignore_missing_object => true
84
+ }
85
+ @context.database.each(each_options).find_all do |object|
86
+ object.is_a?(Groonga::Type)
87
+ end
88
+ end
89
+
90
+ def create_tables(schema)
91
+ each_table do |table|
92
+ create_table(schema, table)
93
+ end
94
+ end
95
+
96
+ def create_table(schema, table)
97
+ options = {
98
+ :type => table.type_symbol,
99
+ :key_type => table.key_type_groonga,
100
+ :default_tokenizer => table.tokenizer,
101
+ :normalizer => table.normalizer,
102
+ }
103
+ schema.create_table(table.name, options) do |table_definition|
104
+ each_column(table) do |column|
105
+ next unless normal_column?(column)
106
+ create_data_column(table_definition, column)
107
+ end
108
+ end
109
+ end
110
+
111
+ def create_data_column(table_definition, column)
112
+ options = {
113
+ :type => column.type_symbol,
114
+ }
115
+ if options[:type] == :vector
116
+ options[:with_weight] = true if column.vector_options.weight
117
+ end
118
+ table_definition.column(column.name, column.value_type_groonga, options)
119
+ end
120
+
121
+ def create_reference_columns(schema)
122
+ each_table do |table|
123
+ reference_columns = []
124
+ each_column(table) do |column|
125
+ reference_columns << column if reference_column?(column)
126
+ end
127
+ next if reference_columns.empty?
128
+
129
+ schema.change_table(table.name) do |table_definition|
130
+ reference_columns.each do |column|
131
+ create_data_column(table_definition, column)
132
+ end
133
+ end
134
+ end
135
+ end
136
+
137
+ def create_index_columns(schema)
138
+ each_table do |table|
139
+ index_columns = []
140
+ each_column(table) do |column|
141
+ index_columns << column if index_column?(column)
142
+ end
143
+ next if index_columns.empty?
144
+
145
+ schema.change_table(table.name) do |table_definition|
146
+ index_columns.each do |column|
147
+ create_index_column(table_definition, column)
148
+ end
149
+ end
150
+ end
151
+ end
152
+
153
+ def create_index_column(table_definition, column)
154
+ sources = column.index_options.sources || []
155
+ options = {
156
+ :with_section => column.index_options.section,
157
+ :with_weight => column.index_options.weight,
158
+ :with_position => column.index_options.position,
159
+ }
160
+ table_definition.index(column.value_type_groonga, *sources, options)
161
+ end
162
+
163
+ def log_tag
164
+ "schema_applier"
165
+ end
166
+ end
167
+ end
@@ -0,0 +1,67 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # Copyright (C) 2014 Droonga Project
4
+ #
5
+ # This library is free software; you can redistribute it and/or
6
+ # modify it under the terms of the GNU Lesser General Public
7
+ # License version 2.1 as published by the Free Software Foundation.
8
+ #
9
+ # This library is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
+ # Lesser General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU Lesser General Public
15
+ # License along with this library; if not, write to the Free Software
16
+ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
+
18
+ require "MeCab"
19
+
20
+ module Droonga
21
+ class Searcher
22
+ class QuerySearcher
23
+ class MeCabTokenizer
24
+ def initialize
25
+ @mecab = MeCab::Tagger.new("-Owakati")
26
+ end
27
+
28
+ def tokenize(text)
29
+ tokens = @mecab.parse(text).force_encoding("utf-8").split(/\s+/)
30
+ tokens.reject do |token|
31
+ token.empty?
32
+ end
33
+ end
34
+ end
35
+
36
+ def apply_mecab_filter(condition)
37
+ return unless condition.is_a?(Hash)
38
+ return unless condition["useMeCabFilter"]
39
+ query = condition["query"]
40
+ return if query.nil?
41
+ match_columns = condition["matchTo"]
42
+ return unless match_columns.is_a?(Array)
43
+ return if match_columns.size != 1
44
+ match_column = match_columns.first
45
+
46
+ tokenizer = MeCabTokenizer.new
47
+
48
+ @records.open_cursor do |cursor|
49
+ count = 0
50
+ cursor.each do |record|
51
+ match_target = record[match_column]
52
+ body_terms = tokenizer.tokenize(match_target)
53
+ unless body_terms.include?(query)
54
+ record.delete
55
+ end
56
+ end
57
+ end
58
+ end
59
+
60
+ alias_method :original_apply_condition!, :apply_condition!
61
+ def apply_condition!(condition)
62
+ original_apply_condition!(condition)
63
+ apply_mecab_filter(condition)
64
+ end
65
+ end
66
+ end
67
+ end