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,63 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # Copyright (C) 2013-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 "pathname"
19
+
20
+ require "droonga/loggable"
21
+
22
+ module Droonga
23
+ class PluginLoader
24
+ include Loggable
25
+
26
+ class << self
27
+ def load_all
28
+ loader = new
29
+ loader.load_all
30
+ end
31
+ end
32
+
33
+ def initialize
34
+ end
35
+
36
+ def load(name)
37
+ logger.debug("loading...: <#{name}>")
38
+ path = "droonga/plugins/#{name}"
39
+ begin
40
+ require path
41
+ rescue StandardError, SyntaxError => error
42
+ logger.exception("failed to load: <#{path}>", error)
43
+ raise
44
+ end
45
+ end
46
+
47
+ def load_all
48
+ $LOAD_PATH.each do |load_path|
49
+ search_pattern = "#{load_path}/droonga/plugins/*.rb"
50
+ logger.debug("searching...: <#{search_pattern}>")
51
+ Pathname.glob(search_pattern) do |plugin_path|
52
+ name = Pathname(plugin_path).basename(".rb").to_s
53
+ load(name)
54
+ end
55
+ end
56
+ end
57
+
58
+ private
59
+ def log_tag
60
+ "plugin-loader"
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,66 @@
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
+ module Droonga
17
+ class PluginRegistry
18
+ include Enumerable
19
+
20
+ class UnknownPlugin < Error
21
+ def initialize(name, klass)
22
+ super("[#{klass}] Plugin not found: <#{name}>")
23
+ end
24
+ end
25
+
26
+ def initialize
27
+ @plugins = {}
28
+ end
29
+
30
+ def each(&block)
31
+ @plugins.each(&block)
32
+ end
33
+
34
+ def register(name, plugin_module)
35
+ @plugins[name] = plugin_module
36
+ end
37
+
38
+ def [](name)
39
+ @plugins[name]
40
+ end
41
+
42
+ def clear
43
+ @plugins.clear
44
+ end
45
+
46
+ def find_sub_classes(name, klass)
47
+ plugin_module = self[name]
48
+ if plugin_module.nil?
49
+ raise UnknownPlugin.new(name, klass)
50
+ end
51
+ sub_classes = []
52
+ collect_sub_classes_recursive(plugin_module, klass, sub_classes)
53
+ sub_classes
54
+ end
55
+
56
+ private
57
+ def collect_sub_classes_recursive(base, klass, sub_classes)
58
+ base.constants.each do |constant_name|
59
+ constant = base.const_get(constant_name)
60
+ next unless constant.is_a?(Module)
61
+ sub_classes << constant if constant < klass
62
+ collect_sub_classes_recursive(constant, klass, sub_classes)
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,54 @@
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/plugin"
17
+ require "droonga/reducer"
18
+
19
+ module Droonga
20
+ module Plugins
21
+ module Basic
22
+ extend Plugin
23
+ register("basic")
24
+
25
+ class GatherCollector < Droonga::Collector
26
+ message.pattern = ["task.step.type", :equal, "gather"]
27
+
28
+ def collect(message)
29
+ output = message.input || message.name
30
+ if output.is_a?(Hash)
31
+ output_name = output["output"]
32
+ else
33
+ output_name = output
34
+ end
35
+ message.values[output_name] = message.value
36
+ end
37
+ end
38
+
39
+ class ReduceCollector < Droonga::Collector
40
+ message.pattern = ["task.step.type", :equal, "reduce"]
41
+
42
+ def collect(message)
43
+ message.input.each do |output_name, deal|
44
+ left_value = message.values[output_name]
45
+ right_value = message.value
46
+ reducer = Reducer.new(deal)
47
+ value = reducer.reduce(left_value, right_value)
48
+ message.values[output_name] = value
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,145 @@
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 "groonga"
17
+
18
+ require "droonga/plugin"
19
+ require "droonga/error_messages"
20
+
21
+ module Droonga
22
+ module Plugins
23
+ module CRUD
24
+ extend Plugin
25
+ register("crud")
26
+
27
+ class Adapter < Droonga::Adapter
28
+ input_message.pattern = ["type", :equal, "add"]
29
+ output_message.pattern = ["body.success", :exist]
30
+
31
+ def adapt_input(input_message)
32
+ request = input_message.body
33
+ key = request["key"] || rand.to_s
34
+ values = request["values"] || {}
35
+ request["filter"] = values.merge("_key" => key)
36
+ end
37
+
38
+ def adapt_output(output_message)
39
+ if output_message.errors
40
+ detail = output_message.body["detail"]
41
+ return if detail.nil?
42
+ detail.delete("filter")
43
+ output_message.errors.each do |path, error|
44
+ error["body"]["detail"].delete("filter")
45
+ end
46
+ else
47
+ output_message.body.delete("filter")
48
+ end
49
+ end
50
+ end
51
+
52
+ class Handler < Droonga::Handler
53
+ class MissingTableParameter < BadRequest
54
+ def initialize
55
+ super("\"table\" must be specified.")
56
+ end
57
+ end
58
+
59
+ class MissingPrimaryKeyParameter < BadRequest
60
+ def initialize(table_name)
61
+ super("\"key\" must be specified. " +
62
+ "The table #{table_name.inspect} requires a primary key for a new record.")
63
+ end
64
+ end
65
+
66
+ class UnknownTable < NotFound
67
+ def initialize(table_name)
68
+ super("The table #{table_name.inspect} does not exist in the dataset.")
69
+ end
70
+ end
71
+
72
+ class InvalidValue < BadRequest
73
+ def initialize(column, value, request)
74
+ super("The column #{column.inspect} cannot store the value #{value.inspect}.",
75
+ request)
76
+ end
77
+ end
78
+
79
+ class UnknownColumn < NotFound
80
+ def initialize(column, table, request)
81
+ super("The column #{column.inspect} does not exist in the table #{table.inspect}.",
82
+ request)
83
+ end
84
+ end
85
+
86
+ def handle(message)
87
+ process_add(message.request)
88
+ end
89
+
90
+ private
91
+ def process_add(request)
92
+ raise MissingTableParameter.new unless request.include?("table")
93
+
94
+ table = @context[request["table"]]
95
+ raise UnknownTable.new(request["table"]) unless table
96
+
97
+ if table.support_key?
98
+ unless request.include?("key")
99
+ raise MissingPrimaryKeyParameter.new(request["table"])
100
+ end
101
+ end
102
+
103
+ add_record(table, request)
104
+ true
105
+ end
106
+
107
+ def add_record(table, request)
108
+ record = nil
109
+ if table.support_key?
110
+ record = table.add(request["key"])
111
+ else
112
+ record = table.add
113
+ end
114
+ (request["values"] || []).each do |column, value|
115
+ begin
116
+ record[column] = value
117
+ rescue ::Groonga::InvalidArgument => error
118
+ record.delete if record.added?
119
+ raise InvalidValue.new(column, value, request)
120
+ rescue ArgumentError => error
121
+ record.delete if record.added?
122
+ raise InvalidValue.new(column, value, request)
123
+ rescue ::Groonga::NoSuchColumn => error
124
+ record.delete if record.added?
125
+ raise UnknownColumn.new(column, request["table"], request)
126
+ end
127
+ end
128
+ end
129
+ end
130
+
131
+ define_single_step do |step|
132
+ step.name = "add"
133
+ step.inputs = {
134
+ "table" => {
135
+ :type => :table,
136
+ :filter => "filter",
137
+ },
138
+ }
139
+ step.write = true
140
+ step.handler = Handler
141
+ step.collector = Collectors::And
142
+ end
143
+ end
144
+ end
145
+ end
@@ -0,0 +1,97 @@
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 "groonga"
17
+
18
+ require "droonga/plugin"
19
+ require "droonga/error_messages"
20
+
21
+ module Droonga
22
+ module Plugins
23
+ module Dump
24
+ extend Plugin
25
+ register("dump")
26
+
27
+ class Handler < Droonga::Handler
28
+ def handle(message)
29
+ replyTo = (message.raw["replyTo"] || {})["to"]
30
+ return false unless replyTo
31
+
32
+ request = message.request || {}
33
+ messages_per_seconds = request["messagesPerSecond"] || 10000
34
+ messages_per_seconds = [10, messages_per_seconds.to_i].max
35
+ messages_per_100msec = messages_per_seconds / 10
36
+ dumper = Enumerator.new do |yielder|
37
+ n = 0
38
+ each_table do |table|
39
+ table.each do |record|
40
+ values = {}
41
+ record.attributes.each do |key, value|
42
+ values[key] = value unless key.start_with?("_")
43
+ end
44
+ dump_message = {
45
+ "dataset" => message.raw["dataset"],
46
+ "body" => {
47
+ "table" => table.name,
48
+ "key" => record.key,
49
+ "values" => values,
50
+ },
51
+ }
52
+ messenger.forward(dump_message,
53
+ "to" => replyTo,
54
+ "type" => "dump.record")
55
+ n = (n + 1) % messages_per_100msec
56
+ yielder << nil if n.zero?
57
+ end
58
+ end
59
+ end
60
+
61
+ timer = Coolio::TimerWatcher.new(0.1, true)
62
+ timer.on_timer do
63
+ begin
64
+ dumper.next
65
+ rescue StopIteration
66
+ timer.detach
67
+ end
68
+ end
69
+ loop.attach(timer)
70
+
71
+ true
72
+ end
73
+
74
+ private
75
+ def each_table
76
+ @context.database.each(:ignore_missing_object => true) do |object|
77
+ next unless object.is_a?(::Groonga::Table)
78
+ next if index_only_table?(object)
79
+ yield(object)
80
+ end
81
+ end
82
+
83
+ def index_only_table?(table)
84
+ table.columns.all? do |column|
85
+ column.is_a?(::Groonga::IndexColumn)
86
+ end
87
+ end
88
+ end
89
+
90
+ define_single_step do |step|
91
+ step.name = "dump"
92
+ step.handler = Handler
93
+ step.collector = Collectors::And
94
+ end
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,51 @@
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/plugin"
17
+
18
+ module Droonga
19
+ module Plugins
20
+ module Error
21
+ extend Plugin
22
+ register("error")
23
+
24
+ class Adapter < Droonga::Adapter
25
+ output_message.pattern = ["body.errors", :exist]
26
+
27
+ def adapt_output(output_message)
28
+ errors = output_message.body["errors"]
29
+ if errors and !errors.empty?
30
+ output_message.errors = errors
31
+
32
+ status_codes = []
33
+ errors.values.each do |error|
34
+ status_codes << error["statusCode"]
35
+ end
36
+ status_codes = status_codes.uniq
37
+ if status_codes.size == 1
38
+ output_message.status_code = status_codes.first
39
+ else
40
+ output_message.status_code = ErrorMessages::InternalServerError::STATUS_CODE
41
+ end
42
+
43
+ output_message.body = errors.values.first["body"]
44
+ else
45
+ output_message.body.delete("errors")
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,123 @@
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 "groonga/command/column-create"
17
+
18
+ require "droonga/plugin"
19
+ require "droonga/plugins/groonga/generic_command"
20
+
21
+ module Droonga
22
+ module Plugins
23
+ module Groonga
24
+ module ColumnCreate
25
+ class Command < GenericCommand
26
+ def process_request(request)
27
+ command_class = ::Groonga::Command.find("column_create")
28
+ @command = command_class.new("column_create", request)
29
+
30
+ table_name = valid_table_name("table")
31
+
32
+ if @command.column_index?
33
+ define_index(table_name)
34
+ else
35
+ define_column(table_name)
36
+ end
37
+ end
38
+
39
+ private
40
+ def define_column(table_name)
41
+ column_name = @command["name"]
42
+ column_type = @command["type"]
43
+
44
+ options = create_column_options
45
+ ::Groonga::Schema.define(:context => @context) do |schema|
46
+ schema.change_table(table_name) do |table|
47
+ table.column(column_name, column_type, options)
48
+ end
49
+ end
50
+ true
51
+ end
52
+
53
+ def create_column_options
54
+ options = {}
55
+ create_column_options_flags(options)
56
+ options
57
+ end
58
+
59
+ def create_column_options_flags(options)
60
+ options[:type] = :scalar
61
+ if @command.column_scalar?
62
+ options[:type] = :scalar
63
+ elsif @command.column_vector?
64
+ options[:type] = :vector
65
+ if @command.with_weight?
66
+ options[:with_weight] = true
67
+ end
68
+ end
69
+ options
70
+ end
71
+
72
+ def define_index(table_name)
73
+ target_table = @command["type"]
74
+ target_columns = (@command["source"] || "").split(/\s*,\s*/)
75
+
76
+ options = create_index_options
77
+ ::Groonga::Schema.define(:context => @context) do |schema|
78
+ schema.change_table(table_name) do |table|
79
+ arguments = [target_table, *target_columns]
80
+ arguments << options
81
+ table.index(*arguments)
82
+ end
83
+ end
84
+ true
85
+ end
86
+
87
+ def create_index_options
88
+ options = {}
89
+ create_index_options_name(options)
90
+ create_index_options_flags(options)
91
+ options
92
+ end
93
+
94
+ def create_index_options_name(options)
95
+ options[:name] = @command["name"]
96
+ end
97
+
98
+ def create_index_options_flags(options)
99
+ options[:with_section] = true if @command.with_section?
100
+ options[:with_weight] = true if @command.with_weight?
101
+ options[:with_position] = true if @command.with_position?
102
+ end
103
+ end
104
+
105
+ class Handler < Droonga::Handler
106
+ action.synchronous = true
107
+
108
+ def handle(message)
109
+ command = Command.new(@context)
110
+ command.execute(message.request)
111
+ end
112
+ end
113
+
114
+ Groonga.define_single_step do |step|
115
+ step.name = "column_create"
116
+ step.write = true
117
+ step.handler = Handler
118
+ step.collector = Collectors::Or
119
+ end
120
+ end
121
+ end
122
+ end
123
+ end