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,143 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # Copyright (C) 2013 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
+ # this benchmark must be done by benchmark-notify.sh.
19
+
20
+ require "benchmark"
21
+ require "fileutils"
22
+ require "optparse"
23
+ require "csv"
24
+ require "json"
25
+
26
+ require "droonga/client"
27
+
28
+ require File.expand_path(File.join(__FILE__, "..", "..", "utils.rb"))
29
+
30
+ class NotifyBenchmark
31
+ attr_reader :n_subscribers
32
+
33
+ WATCHING_KEYWORD = "a"
34
+
35
+ def initialize(params)
36
+ @params = params || {}
37
+ @n_times = params[:n_times] || 0
38
+ @timeout = params[:timeout] || 0
39
+
40
+ @n_subscribers = 0
41
+
42
+ @client = Droonga::Client.new(tag: "droonga", port: 23003)
43
+ @receiver = DroongaBenchmark::MessageReceiver.new
44
+ @route = "#{@receiver.host}:#{@receiver.port}/droonga"
45
+ setup
46
+ end
47
+
48
+ def setup
49
+ add_subscribers(@params[:n_initial_subscribers])
50
+ end
51
+
52
+ def run
53
+ @n_times.times do |index|
54
+ do_feed("#{WATCHING_KEYWORD} #{index}")
55
+ end
56
+
57
+ published_messages = []
58
+ while published_messages.size != @n_times
59
+ published_messages << @receiver.new_message
60
+ end
61
+ published_messages
62
+ end
63
+
64
+ def add_subscribers(n_subscribers)
65
+ n_subscribers.times do |index|
66
+ message = DroongaBenchmark::MessageCreator.envelope_to_subscribe(WATCHING_KEYWORD)
67
+ message["body"]["subscriber"] += " #{@n_subscribers + index}"
68
+ message["body"]["route"] = @route
69
+ @client.connection.send(message, :response => :one)
70
+ end
71
+ @n_subscribers += n_subscribers
72
+ end
73
+
74
+ def do_feed(target)
75
+ message = DroongaBenchmark::MessageCreator.envelope_to_feed(target)
76
+ @client.connection.send(message, :response => :none)
77
+ end
78
+ end
79
+
80
+ options = {
81
+ :n_subscribers => 1000,
82
+ :n_times => 1000,
83
+ :n_steps => 10,
84
+ :output_path => "/tmp/watch-benchmark-notify.csv",
85
+ }
86
+ option_parser = OptionParser.new do |parser|
87
+ parser.on("--subscribers=N", Integer,
88
+ "initial number of subscribers") do |n_subscribers|
89
+ options[:n_subscribers] = n_subscribers
90
+ end
91
+ parser.on("--times=N", Integer,
92
+ "number of publish times") do |n_times|
93
+ options[:n_times] = n_times
94
+ end
95
+ parser.on("--steps=N", Integer,
96
+ "number of benchmark steps") do |n_steps|
97
+ options[:n_steps] = n_steps
98
+ end
99
+ parser.on("--timeout=N", Float,
100
+ "timeout for receiving") do |timeout|
101
+ options[:timeout] = timeout
102
+ end
103
+ parser.on("--output-path=PATH", String,
104
+ "path to the output CSV file") do |output_path|
105
+ options[:output_path] = output_path
106
+ end
107
+ end
108
+ args = option_parser.parse!(ARGV)
109
+
110
+
111
+ notify_benchmark = NotifyBenchmark.new(:n_initial_subscribers => options[:n_subscribers],
112
+ :n_times => options[:n_times],
113
+ :timeout => options[:timeout])
114
+ results = []
115
+ options[:n_steps].times do |try_count|
116
+ notify_benchmark.add_subscribers(notify_benchmark.n_subscribers) if try_count > 0
117
+ label = "#{notify_benchmark.n_subscribers} subscribers"
118
+ percentage = nil
119
+ result = Benchmark.bm do |benchmark|
120
+ benchmark.report(label) do
121
+ published_messages = notify_benchmark.run
122
+ percentage = published_messages.size.to_f / options[:n_times] * 100
123
+ end
124
+ end
125
+ puts "=> #{percentage} % feeds are notified"
126
+ result = result.join("").strip.gsub(/[()]/, "").split(/\s+/)
127
+ qps = options[:n_times].to_f / result.last.to_f
128
+ puts " (#{qps} queries per second)"
129
+ results << [label, qps]
130
+ end
131
+ total_results = [
132
+ ["case", "qps"],
133
+ ]
134
+ total_results += results
135
+
136
+ puts ""
137
+ puts "Results (saved to #{options[:output_path]}):"
138
+ File.open(options[:output_path], "w") do |file|
139
+ total_results.each do |row|
140
+ file.puts(CSV.generate_line(row))
141
+ puts row.join(",")
142
+ end
143
+ end
@@ -0,0 +1,20 @@
1
+ #!/bin/sh
2
+
3
+ base_dir=$(cd $(dirname $0); pwd)
4
+ work_dir=$base_dir/../../performance/watch
5
+
6
+ rm -rf $base_dir/watch
7
+ mkdir -p $base_dir/watch
8
+
9
+ DROONGA_CATALOG=$work_dir/catalog.json \
10
+ bundle exec fluentd \
11
+ --config $work_dir/fluentd.conf &
12
+ FLUENTD_PID=$!
13
+
14
+ sleep 1
15
+
16
+ bundle exec ruby $base_dir/benchmark-notify.rb "$@"
17
+
18
+ kill $FLUENTD_PID
19
+ wait $FLUENTD_PID
20
+
@@ -0,0 +1,120 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # Copyright (C) 2013 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 "benchmark"
19
+ require "fileutils"
20
+ require "optparse"
21
+ require "csv"
22
+
23
+ require "groonga"
24
+
25
+ require "droonga/watcher"
26
+ require File.expand_path(File.join(__FILE__, "..", "..", "utils.rb"))
27
+
28
+ class PublishBenchmark
29
+ attr_reader :n_subscribers
30
+
31
+ def initialize(n_initial_subscribers)
32
+ @database = DroongaBenchmark::WatchDatabase.new
33
+ @watcher = Droonga::Watcher.new(@database.context)
34
+ @keywords_generator = DroongaBenchmark::KeywordsGenerator.new
35
+ @keywords = []
36
+ @n_subscribers = 0
37
+ add_subscribers(n_initial_subscribers)
38
+ end
39
+
40
+ def run
41
+ @matched_keywords.each do |keyword|
42
+ publish(keyword)
43
+ end
44
+ end
45
+
46
+ def prepare_keywords(n_keywords)
47
+ @matched_keywords = @keywords.sample(n_keywords)
48
+ end
49
+
50
+ def add_subscribers(n_subscribers)
51
+ new_keywords = []
52
+ n_subscribers.times do
53
+ new_keywords << @keywords_generator.next
54
+ end
55
+ @database.subscribe_to(new_keywords)
56
+ @keywords += new_keywords
57
+ @n_subscribers += n_subscribers
58
+ end
59
+
60
+ private
61
+ def publish(matched_keyword)
62
+ @watcher.publish([matched_keyword], {}) do |route, subscribers|
63
+ end
64
+ end
65
+ end
66
+
67
+ options = {
68
+ :n_subscribers => 1000,
69
+ :n_times => 1000,
70
+ :n_steps => 10,
71
+ :output_path => "/tmp/watch-benchmark-notify.csv",
72
+ }
73
+ option_parser = OptionParser.new do |parser|
74
+ parser.on("--subscribers=N", Integer,
75
+ "initial number of subscribers (optional)") do |n_subscribers|
76
+ options[:n_subscribers] = n_subscribers
77
+ end
78
+ parser.on("--times=N", Integer,
79
+ "number of publish times (optional)") do |n_times|
80
+ options[:n_times] = n_times
81
+ end
82
+ parser.on("--steps=N", Integer,
83
+ "number of benchmark steps (optional)") do |n_steps|
84
+ options[:n_steps] = n_steps
85
+ end
86
+ parser.on("--output-path=PATH", String,
87
+ "path to the output CSV file (optional)") do |output_path|
88
+ options[:output_path] = output_path
89
+ end
90
+ end
91
+ args = option_parser.parse!(ARGV)
92
+
93
+
94
+ publish_benchmark = PublishBenchmark.new(options[:n_subscribers])
95
+ results = []
96
+ options[:n_steps].times do |try_count|
97
+ publish_benchmark.add_subscribers(publish_benchmark.n_subscribers) if try_count > 0
98
+ label = "#{publish_benchmark.n_subscribers} subscribers"
99
+ result = Benchmark.bmbm do |benchmark|
100
+ publish_benchmark.prepare_keywords(options[:n_times])
101
+ benchmark.report(label) do
102
+ publish_benchmark.run
103
+ end
104
+ end
105
+ result = result.join("").strip.gsub(/[()]/, "").split(/\s+/)
106
+ results << [label] + result
107
+ end
108
+ total_results = [
109
+ ["case", "user", "system", "total", "real"],
110
+ ]
111
+ total_results += results
112
+
113
+ puts ""
114
+ puts "Results (saved to #{options[:output_path]}):"
115
+ File.open(options[:output_path], "w") do |file|
116
+ total_results.each do |row|
117
+ file.puts(CSV.generate_line(row))
118
+ puts row.join(",")
119
+ end
120
+ end
@@ -0,0 +1,213 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # Copyright (C) 2013 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 "benchmark"
19
+ require "fileutils"
20
+ require "optparse"
21
+ require "csv"
22
+ require "fluent/log"
23
+
24
+ require "groonga"
25
+
26
+ require "droonga/watcher"
27
+ require File.expand_path(File.join(__FILE__, "..", "..", "utils.rb"))
28
+
29
+ $log = Fluent::Log.new
30
+
31
+ class ScanBenchmark
32
+ attr_reader :n_keywords
33
+
34
+ def initialize(n_times, options={})
35
+ @n_times = n_times
36
+ @incidence = options[:incidence]
37
+
38
+ @database = DroongaBenchmark::WatchDatabase.new
39
+
40
+ @watcher = Droonga::Watcher.new(@database.context)
41
+
42
+ @keywords_generator = DroongaBenchmark::KeywordsGenerator.new
43
+ @keywords = @keywords_generator.generate(@n_times)
44
+ prepare_targets(options)
45
+
46
+ @database.subscribe_to(@keywords)
47
+ @n_keywords = @keywords.size
48
+
49
+ @hits = []
50
+ end
51
+
52
+ def run
53
+ @targets.each do |target|
54
+ scan(target)
55
+ end
56
+ end
57
+
58
+ def prepare_targets(options={})
59
+ @incidence = options[:incidence] || 0
60
+ @matched_keywords = options[:matched_keywords] || 0
61
+ @targets = DroongaBenchmark::TargetsGenerator.generate(@n_times,
62
+ :keywords => @keywords.sample(@n_times),
63
+ :incidence => @incidence,
64
+ :matched_keywords => @matched_keywords)
65
+ end
66
+
67
+ def add_keywords(n_keywords)
68
+ new_keywords = []
69
+ n_keywords.times do
70
+ new_keywords << @keywords_generator.next
71
+ end
72
+ @database.subscribe_to(new_keywords)
73
+ @keywords += new_keywords
74
+ @n_keywords += n_keywords
75
+ end
76
+
77
+ def memory_usage
78
+ /^VmRSS:\s*(\d+) kB/ =~ File.read("/proc/self/status")
79
+ $1.to_i * 1024
80
+ end
81
+
82
+ private
83
+ def scan(target)
84
+ @watcher.scan_body(@hits, target)
85
+ @hits.clear
86
+ end
87
+ end
88
+
89
+ options = {
90
+ :n_watching_keywords => 1000,
91
+ :n_steps => 10,
92
+ :incidences => "0.1,0.5,0.9",
93
+ :matched_keywords => "1,5,10",
94
+ :output_path => "/tmp/watch-benchmark-scan",
95
+ }
96
+ option_parser = OptionParser.new do |parser|
97
+ parser.on("--keywords=N", Integer,
98
+ "number of watching keywords") do |n_watching_keywords|
99
+ options[:n_watching_keywords] = n_watching_keywords
100
+ end
101
+ parser.on("--steps=N", Integer,
102
+ "number of benchmark steps") do |n_steps|
103
+ options[:n_steps] = n_steps
104
+ end
105
+ parser.on("--incidences=INCIDENCES", String,
106
+ "list of matching incidences") do |incidences|
107
+ options[:incidences] = incidences
108
+ end
109
+ parser.on("--matched-keywords=MATCHED_KEYWORDS", String,
110
+ "number of keywords which is matched per a target") do |matched_keywords|
111
+ options[:matched_keywords] = matched_keywords
112
+ end
113
+ parser.on("--output-path=PATH", String,
114
+ "path to the output CSV file") do |output_path|
115
+ options[:output_path] = output_path
116
+ end
117
+ end
118
+ args = option_parser.parse!(ARGV)
119
+
120
+ results_for_specific_condition = {}
121
+ scan_benchmark = ScanBenchmark.new(options[:n_watching_keywords])
122
+ options[:n_steps].times do |try_count|
123
+ scan_benchmark.add_keywords(scan_benchmark.n_keywords) if try_count > 0
124
+ GC.start
125
+ sleep 1
126
+ puts "\n=============== #{scan_benchmark.n_keywords} keywords ===============\n"
127
+ options[:incidences].split(/[,\s]+/).each do |incidence|
128
+ incidence = incidence.to_f
129
+ options[:matched_keywords].split(/[,\s]+/).each do |matched_keywords|
130
+ matched_keywords = matched_keywords.to_i
131
+
132
+ GC.disable
133
+
134
+ condition = "#{incidence * 100}%/#{matched_keywords}match"
135
+ results_for_specific_condition[condition] ||= []
136
+ label = "#{incidence * 100} %/#{matched_keywords} match/#{scan_benchmark.n_keywords} keywords"
137
+
138
+ result = Benchmark.bmbm do |benchmark|
139
+ scan_benchmark.prepare_targets(:incidence => incidence,
140
+ :matched_keywords => matched_keywords)
141
+ benchmark.report(label) do
142
+ scan_benchmark.run
143
+ end
144
+ end
145
+
146
+ result = result.join("").strip.gsub(/[()]/, "").split(/\s+/)
147
+ result << scan_benchmark.memory_usage
148
+ results_for_specific_condition[condition] << [label] + result
149
+
150
+ GC.enable
151
+ GC.start
152
+ sleep 1
153
+ end
154
+ end
155
+ end
156
+
157
+ FileUtils.mkdir_p(options[:output_path])
158
+
159
+ puts ""
160
+ all_output = File.join(options[:output_path], "all.csv")
161
+ all_results = [
162
+ ["case", "user", "system", "total", "real"],
163
+ ]
164
+ results_for_specific_condition.values.each do |results|
165
+ all_results += results
166
+ end
167
+ puts "All (saved to #{all_output}):"
168
+ File.open(all_output, "w") do |file|
169
+ all_results.each do |row|
170
+ file.puts(CSV.generate_line(row))
171
+ puts row.join(",")
172
+ end
173
+ end
174
+
175
+ puts ""
176
+ total_output = File.join(options[:output_path], "total.csv")
177
+ total_results_header = ["case"]
178
+ total_results = []
179
+ results_for_specific_condition.each do |condition, results|
180
+ total_results_header << condition
181
+ results.each_index do |index|
182
+ total_results[index] ||= [results[index].first.split("/").last]
183
+ total_results[index] << results[index][3]
184
+ end
185
+ end
186
+ total_results.unshift(total_results_header)
187
+ puts "Total (saved to #{total_output}):"
188
+ File.open(total_output, "w") do |file|
189
+ total_results.each do |row|
190
+ file.puts(CSV.generate_line(row))
191
+ puts row.join(",")
192
+ end
193
+ end
194
+
195
+ puts ""
196
+ real_output = File.join(options[:output_path], "real.csv")
197
+ real_results_header = ["case"]
198
+ real_results = []
199
+ results_for_specific_condition.each do |condition, results|
200
+ real_results_header << condition
201
+ results.each_index do |index|
202
+ real_results[index] ||= [results[index].first.split("/").last]
203
+ real_results[index] << results[index][4]
204
+ end
205
+ end
206
+ real_results.unshift(real_results_header)
207
+ puts "Real (saved to #{real_output}):"
208
+ File.open(real_output, "w") do |file|
209
+ real_results.each do |row|
210
+ file.puts(CSV.generate_line(row))
211
+ puts row.join(",")
212
+ end
213
+ end
@@ -0,0 +1,103 @@
1
+ #!/usr/bin/env ruby
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 "ostruct"
19
+ require "optparse"
20
+ require "json"
21
+
22
+ require "droonga/engine/version"
23
+ require "droonga/catalog_generator"
24
+
25
+ generator = Droonga::CatalogGenerator.new
26
+ current_dataset = nil
27
+ datasets = {}
28
+
29
+ options = OpenStruct.new
30
+ options.output_path = "-"
31
+ parser = OptionParser.new
32
+ parser.version = Droonga::Engine::VERSION
33
+ parser.on("--output=PATH",
34
+ "Output catalog.json to PATH.",
35
+ "\"-\" means the standard output.",
36
+ "(#{options.output_path})") do |path|
37
+ options.output_path = path
38
+ end
39
+ parser.on("--dataset=NAME",
40
+ "Add a dataset its name is NAME.",
41
+ "And set the NAME to the current dataset.") do |name|
42
+ current_dataset = datasets[name] = {}
43
+ end
44
+ parser.on("--n-workers=N", Integer,
45
+ "Use N workers for the current dataset.") do |n|
46
+ current_dataset[:n_workers] = n
47
+ end
48
+ parser.on("--hosts=NAME1,NAME2,...", Array,
49
+ "Use given hosts for replicas of the current dataset.") do |hosts|
50
+ current_dataset[:hosts] = hosts
51
+ end
52
+ parser.on("--port=PORT", Integer,
53
+ "Use the PORT as the port for the current dataset.") do |port|
54
+ current_dataset[:port] = port
55
+ end
56
+ parser.on("--tag=TAG",
57
+ "Use the TAG as the tag for the current dataset.") do |tag|
58
+ current_dataset[:tag] = tag
59
+ end
60
+ parser.on("--n-slices=N", Integer,
61
+ "Use N slices for each replica.") do |n|
62
+ current_dataset[:n_slices] = n
63
+ end
64
+ parser.on("--plugins=PLUGIN1,PLUGIN2,...", Array,
65
+ "Use PLUGINS for the current dataset.") do |plugins|
66
+ current_dataset[:plugins] = plugins
67
+ end
68
+ parser.on("--schema=PATH",
69
+ "Use schema in JSON at PATH for the current dataset.") do |path|
70
+ File.open(path) do |input|
71
+ current_dataset[:schema] = JSON.parse(input.read)
72
+ end
73
+ end
74
+ parser.on("--fact=TABLE",
75
+ "Use TABLE as the fact table for the current dataset.") do |table|
76
+ current_dataset[:fact] = table
77
+ end
78
+ parser.on("--replicas=PATH",
79
+ "Use replicas in JSON at PATH for the current dataset.") do |path|
80
+ File.open(path) do |input|
81
+ current_dataset[:replicas] = JSON.parse(input.read)
82
+ end
83
+ end
84
+ parser.parse!(ARGV)
85
+
86
+ datasets.each do |name, options|
87
+ generator.add_dataset(name, options)
88
+ end
89
+
90
+ def open_output(path)
91
+ if path == "-"
92
+ yield($stdout)
93
+ else
94
+ File.open(path, "w") do |output|
95
+ yield(output)
96
+ end
97
+ end
98
+ end
99
+
100
+ catalog = generator.generate
101
+ open_output(options.output_path) do |output|
102
+ output.puts(JSON.pretty_generate(catalog))
103
+ end
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env ruby
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 "droonga/engine/command/droonga_engine"
19
+
20
+ exit(Droonga::Engine::Command::DroongaEngine::Supervisor.run(ARGV))
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env ruby
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 "droonga/engine/command/droonga_engine"
19
+
20
+ exit(Droonga::Engine::Command::DroongaEngine::Service.run(ARGV))