mongo 1.12.5 → 2.0.0

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 (475) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/CONTRIBUTING.md +64 -0
  4. data/LICENSE +1 -1
  5. data/README.md +21 -126
  6. data/Rakefile +39 -21
  7. data/bin/mongo_console +6 -38
  8. data/lib/mongo/address/ipv4.rb +85 -0
  9. data/lib/mongo/address/ipv6.rb +85 -0
  10. data/lib/mongo/address/unix.rb +76 -0
  11. data/lib/mongo/address.rb +111 -0
  12. data/lib/mongo/auth/cr/conversation.rb +119 -0
  13. data/lib/mongo/auth/cr.rb +44 -0
  14. data/lib/mongo/auth/executable.rb +52 -0
  15. data/lib/mongo/auth/ldap/conversation.rb +92 -0
  16. data/lib/mongo/auth/ldap.rb +48 -0
  17. data/lib/mongo/auth/roles.rb +104 -0
  18. data/lib/mongo/auth/scram/conversation.rb +450 -0
  19. data/lib/mongo/auth/scram.rb +53 -0
  20. data/lib/mongo/auth/user/view.rb +102 -0
  21. data/lib/mongo/auth/user.rb +159 -0
  22. data/lib/mongo/auth/x509/conversation.rb +92 -0
  23. data/lib/mongo/auth/x509.rb +48 -0
  24. data/lib/mongo/auth.rb +108 -0
  25. data/lib/mongo/bulk_write/bulk_writable.rb +191 -0
  26. data/lib/mongo/bulk_write/deletable.rb +60 -0
  27. data/lib/mongo/bulk_write/insertable.rb +52 -0
  28. data/lib/mongo/bulk_write/ordered_bulk_write.rb +48 -0
  29. data/lib/mongo/bulk_write/replacable.rb +57 -0
  30. data/lib/mongo/bulk_write/unordered_bulk_write.rb +46 -0
  31. data/lib/mongo/bulk_write/updatable.rb +68 -0
  32. data/lib/mongo/bulk_write.rb +52 -0
  33. data/lib/mongo/client.rb +246 -0
  34. data/lib/mongo/cluster/topology/replica_set.rb +160 -0
  35. data/lib/mongo/cluster/topology/sharded.rb +132 -0
  36. data/lib/mongo/cluster/topology/standalone.rb +132 -0
  37. data/lib/mongo/cluster/topology/unknown.rb +155 -0
  38. data/lib/mongo/cluster/topology.rb +60 -0
  39. data/lib/mongo/cluster.rb +203 -0
  40. data/lib/mongo/collection/view/aggregation.rb +108 -0
  41. data/lib/mongo/collection/view/explainable.rb +49 -0
  42. data/lib/mongo/collection/view/immutable.rb +43 -0
  43. data/lib/mongo/collection/view/iterable.rb +48 -0
  44. data/lib/mongo/collection/view/map_reduce.rb +191 -0
  45. data/lib/mongo/collection/view/readable.rb +363 -0
  46. data/lib/mongo/collection/view/writable.rb +185 -0
  47. data/lib/mongo/collection/view.rb +169 -0
  48. data/lib/mongo/collection.rb +130 -1101
  49. data/lib/mongo/cursor.rb +78 -681
  50. data/lib/mongo/database/view.rb +101 -0
  51. data/lib/mongo/database.rb +224 -0
  52. data/lib/mongo/error/bulk_write_error.rb +41 -0
  53. data/lib/mongo/error/invalid_bulk_operation.rb +36 -0
  54. data/lib/mongo/error/invalid_bulk_operation_type.rb +36 -0
  55. data/lib/mongo/error/invalid_collection_name.rb +39 -0
  56. data/lib/mongo/error/invalid_database_name.rb +39 -0
  57. data/{test/replica_set/ssl_test.rb → lib/mongo/error/invalid_document.rb} +21 -14
  58. data/lib/mongo/error/invalid_file.rb +38 -0
  59. data/lib/mongo/error/invalid_nonce.rb +46 -0
  60. data/lib/mongo/error/invalid_replacement_document.rb +39 -0
  61. data/lib/mongo/error/invalid_signature.rb +47 -0
  62. data/{test/functional/ssl_test.rb → lib/mongo/error/invalid_update_document.rb} +22 -12
  63. data/lib/mongo/error/max_bson_size.rb +40 -0
  64. data/lib/mongo/error/max_message_size.rb +42 -0
  65. data/{test/functional/db_connection_test.rb → lib/mongo/error/multi_index_drop.rb} +17 -8
  66. data/lib/mongo/{utils.rb → error/need_primary_server.rb} +10 -6
  67. data/lib/mongo/{connection.rb → error/operation_failure.rb} +10 -6
  68. data/lib/mongo/error/parser.rb +77 -0
  69. data/lib/mongo/{connection/socket.rb → error/socket_error.rb} +10 -5
  70. data/lib/mongo/error/socket_timeout_error.rb +23 -0
  71. data/lib/mongo/error/unsupported_features.rb +43 -0
  72. data/lib/mongo/error.rb +82 -0
  73. data/lib/mongo/event/listeners.rb +63 -0
  74. data/lib/mongo/event/primary_elected.rb +53 -0
  75. data/lib/mongo/event/publisher.rb +42 -0
  76. data/lib/mongo/event/server_added.rb +53 -0
  77. data/lib/mongo/event/server_removed.rb +53 -0
  78. data/lib/mongo/event/subscriber.rb +41 -0
  79. data/lib/mongo/event.rb +40 -0
  80. data/lib/mongo/grid/file/chunk.rb +184 -0
  81. data/lib/mongo/grid/file/metadata.rb +229 -0
  82. data/lib/mongo/grid/file.rb +106 -0
  83. data/lib/mongo/grid/fs.rb +149 -0
  84. data/lib/mongo/{gridfs.rb → grid.rb} +3 -5
  85. data/lib/mongo/index/view.rb +261 -0
  86. data/lib/mongo/index.rb +64 -0
  87. data/lib/mongo/loggable.rb +126 -0
  88. data/lib/mongo/logger.rb +132 -0
  89. data/lib/mongo/operation/aggregate/result.rb +88 -0
  90. data/lib/mongo/operation/aggregate.rb +100 -0
  91. data/lib/mongo/operation/command.rb +62 -0
  92. data/lib/mongo/operation/executable.rb +105 -0
  93. data/lib/mongo/operation/kill_cursors.rb +39 -0
  94. data/lib/mongo/operation/limited.rb +37 -0
  95. data/lib/mongo/operation/list_collections/result.rb +114 -0
  96. data/lib/mongo/operation/list_indexes/result.rb +118 -0
  97. data/lib/mongo/operation/map_reduce/result.rb +122 -0
  98. data/lib/mongo/operation/map_reduce.rb +96 -0
  99. data/lib/mongo/operation/read/collections_info.rb +67 -0
  100. data/lib/mongo/operation/read/get_more.rb +71 -0
  101. data/lib/mongo/operation/read/indexes.rb +68 -0
  102. data/lib/mongo/operation/read/list_collections.rb +75 -0
  103. data/lib/mongo/operation/read/list_indexes.rb +77 -0
  104. data/lib/mongo/operation/read/query.rb +71 -0
  105. data/lib/mongo/{functional.rb → operation/read.rb} +7 -7
  106. data/lib/mongo/operation/read_preferrable.rb +34 -0
  107. data/lib/mongo/operation/result.rb +259 -0
  108. data/lib/mongo/operation/specifiable.rb +397 -0
  109. data/lib/mongo/operation/write/bulk/bulk_delete/result.rb +75 -0
  110. data/lib/mongo/operation/write/bulk/bulk_delete.rb +144 -0
  111. data/lib/mongo/operation/write/bulk/bulk_insert/result.rb +68 -0
  112. data/lib/mongo/operation/write/bulk/bulk_insert.rb +129 -0
  113. data/lib/mongo/operation/write/bulk/bulk_mergable.rb +67 -0
  114. data/lib/mongo/operation/write/bulk/bulk_update/result.rb +162 -0
  115. data/lib/mongo/operation/write/bulk/bulk_update.rb +153 -0
  116. data/lib/mongo/operation/write/bulk/legacy_bulk_mergable.rb +83 -0
  117. data/lib/mongo/operation/write/bulk.rb +17 -0
  118. data/lib/mongo/operation/write/command/create_index.rb +50 -0
  119. data/lib/mongo/operation/write/command/create_user.rb +43 -0
  120. data/lib/mongo/operation/write/command/delete.rb +56 -0
  121. data/lib/mongo/operation/write/command/drop_index.rb +51 -0
  122. data/lib/mongo/operation/write/command/insert.rb +55 -0
  123. data/lib/mongo/operation/write/command/remove_user.rb +42 -0
  124. data/lib/mongo/operation/write/command/update.rb +60 -0
  125. data/lib/mongo/operation/write/command/writable.rb +61 -0
  126. data/lib/mongo/operation/write/command.rb +22 -0
  127. data/lib/mongo/operation/write/create_index.rb +89 -0
  128. data/lib/mongo/operation/write/create_user.rb +75 -0
  129. data/lib/mongo/operation/write/delete/result.rb +40 -0
  130. data/lib/mongo/operation/write/delete.rb +93 -0
  131. data/lib/mongo/operation/write/drop_index.rb +62 -0
  132. data/lib/mongo/{utils/thread_local_variable_manager.rb → operation/write/insert/result.rb} +15 -8
  133. data/lib/mongo/operation/write/insert.rb +90 -0
  134. data/lib/mongo/operation/write/remove_user.rb +70 -0
  135. data/lib/mongo/operation/write/update/result.rb +160 -0
  136. data/lib/mongo/operation/write/update.rb +103 -0
  137. data/lib/mongo/{connection/socket/socket_util.rb → operation/write.rb} +10 -24
  138. data/lib/mongo/operation.rb +25 -0
  139. data/lib/mongo/options/mapper.rb +78 -0
  140. data/lib/mongo/options.rb +15 -0
  141. data/lib/mongo/protocol/bit_vector.rb +61 -0
  142. data/lib/mongo/protocol/delete.rb +94 -0
  143. data/lib/mongo/protocol/get_more.rb +99 -0
  144. data/lib/mongo/protocol/insert.rb +99 -0
  145. data/lib/mongo/protocol/kill_cursors.rb +74 -0
  146. data/lib/mongo/protocol/message.rb +252 -0
  147. data/lib/mongo/protocol/query.rb +147 -0
  148. data/lib/mongo/protocol/reply.rb +72 -0
  149. data/lib/mongo/protocol/serializers.rb +180 -0
  150. data/lib/mongo/protocol/update.rb +111 -0
  151. data/lib/mongo/protocol.rb +15 -0
  152. data/lib/mongo/server/connectable.rb +110 -0
  153. data/lib/mongo/server/connection.rb +134 -0
  154. data/lib/mongo/server/connection_pool/queue.rb +182 -0
  155. data/lib/mongo/server/connection_pool.rb +141 -0
  156. data/lib/mongo/server/context.rb +66 -0
  157. data/lib/mongo/server/description/features.rb +85 -0
  158. data/lib/mongo/server/description/inspector/primary_elected.rb +58 -0
  159. data/lib/mongo/server/description/inspector/server_added.rb +59 -0
  160. data/lib/mongo/server/description/inspector/server_removed.rb +59 -0
  161. data/lib/mongo/server/description/inspector.rb +79 -0
  162. data/lib/mongo/server/description.rb +450 -0
  163. data/lib/mongo/server/monitor/connection.rb +89 -0
  164. data/lib/mongo/server/monitor.rb +176 -0
  165. data/lib/mongo/server.rb +163 -0
  166. data/lib/mongo/server_selector/nearest.rb +94 -0
  167. data/lib/mongo/server_selector/primary.rb +88 -0
  168. data/lib/mongo/server_selector/primary_preferred.rb +94 -0
  169. data/lib/mongo/server_selector/secondary.rb +91 -0
  170. data/lib/mongo/server_selector/secondary_preferred.rb +96 -0
  171. data/lib/mongo/server_selector/selectable.rb +209 -0
  172. data/lib/mongo/server_selector.rb +81 -0
  173. data/lib/mongo/socket/ssl.rb +130 -0
  174. data/lib/mongo/socket/tcp.rb +69 -0
  175. data/lib/mongo/socket/unix.rb +64 -0
  176. data/lib/mongo/socket.rb +179 -0
  177. data/lib/mongo/uri.rb +504 -0
  178. data/lib/mongo/version.rb +21 -0
  179. data/lib/mongo/write_concern/acknowledged.rb +52 -0
  180. data/lib/mongo/write_concern/normalizable.rb +51 -0
  181. data/lib/mongo/write_concern/unacknowledged.rb +55 -0
  182. data/lib/mongo/write_concern.rb +99 -0
  183. data/lib/mongo.rb +24 -82
  184. data/mongo.gemspec +17 -14
  185. data/spec/certificates/ca.pem +17 -0
  186. data/spec/certificates/client.pem +101 -0
  187. data/spec/certificates/crl.pem +10 -0
  188. data/spec/certificates/crl_client_revoked.pem +12 -0
  189. data/spec/certificates/password_protected.pem +51 -0
  190. data/spec/certificates/server.pem +34 -0
  191. data/spec/mongo/address/ipv4_spec.rb +74 -0
  192. data/spec/mongo/address/ipv6_spec.rb +74 -0
  193. data/spec/mongo/address/unix_spec.rb +30 -0
  194. data/spec/mongo/address_spec.rb +206 -0
  195. data/spec/mongo/auth/cr_spec.rb +59 -0
  196. data/spec/mongo/auth/ldap_spec.rb +40 -0
  197. data/spec/mongo/auth/scram/conversation_spec.rb +197 -0
  198. data/spec/mongo/auth/scram_spec.rb +55 -0
  199. data/spec/mongo/auth/user/view_spec.rb +76 -0
  200. data/spec/mongo/auth/user_spec.rb +190 -0
  201. data/spec/mongo/auth/x509_spec.rb +40 -0
  202. data/spec/mongo/auth_spec.rb +65 -0
  203. data/spec/mongo/bulk/bulk_write_spec.rb +262 -0
  204. data/spec/mongo/client_spec.rb +564 -0
  205. data/spec/mongo/cluster/topology/replica_set_spec.rb +101 -0
  206. data/spec/mongo/cluster/topology/sharded_spec.rb +74 -0
  207. data/spec/mongo/cluster/topology/standalone_spec.rb +79 -0
  208. data/spec/mongo/cluster/topology_spec.rb +65 -0
  209. data/spec/mongo/cluster_spec.rb +129 -0
  210. data/spec/mongo/collection/view/aggregation_spec.rb +148 -0
  211. data/spec/mongo/collection/view/explainable_spec.rb +32 -0
  212. data/spec/mongo/collection/view/map_reduce_spec.rb +242 -0
  213. data/spec/mongo/collection/view/readable_spec.rb +603 -0
  214. data/spec/mongo/collection/view/writable_spec.rb +679 -0
  215. data/spec/mongo/collection/view_spec.rb +530 -0
  216. data/spec/mongo/collection_spec.rb +362 -0
  217. data/spec/mongo/crud_spec.rb +42 -0
  218. data/spec/mongo/cursor_spec.rb +295 -0
  219. data/spec/mongo/database_spec.rb +302 -0
  220. data/spec/mongo/error/parser_spec.rb +119 -0
  221. data/spec/mongo/event/publisher_spec.rb +50 -0
  222. data/spec/mongo/event/subscriber_spec.rb +34 -0
  223. data/spec/mongo/grid/file/chunk_spec.rb +226 -0
  224. data/spec/mongo/grid/file/metadata_spec.rb +92 -0
  225. data/spec/mongo/grid/file_spec.rb +172 -0
  226. data/spec/mongo/grid/fs_spec.rb +129 -0
  227. data/spec/mongo/index/view_spec.rb +330 -0
  228. data/spec/mongo/loggable_spec.rb +62 -0
  229. data/spec/mongo/logger_spec.rb +97 -0
  230. data/spec/mongo/operation/aggregate/result_spec.rb +80 -0
  231. data/spec/mongo/operation/aggregate_spec.rb +127 -0
  232. data/spec/mongo/operation/command_spec.rb +98 -0
  233. data/spec/mongo/operation/kill_cursors_spec.rb +66 -0
  234. data/spec/mongo/operation/limited_spec.rb +50 -0
  235. data/spec/mongo/operation/map_reduce_spec.rb +143 -0
  236. data/spec/mongo/operation/read/collections_info_spec.rb +40 -0
  237. data/spec/mongo/operation/read/get_more_spec.rb +81 -0
  238. data/spec/mongo/operation/read/indexes_spec.rb +31 -0
  239. data/spec/mongo/operation/read/query_spec.rb +84 -0
  240. data/spec/mongo/operation/result_spec.rb +275 -0
  241. data/spec/mongo/operation/specifiable_spec.rb +53 -0
  242. data/spec/mongo/operation/write/bulk_delete_spec.rb +235 -0
  243. data/spec/mongo/operation/write/bulk_insert_spec.rb +235 -0
  244. data/spec/mongo/operation/write/bulk_update_spec.rb +236 -0
  245. data/spec/mongo/operation/write/command/delete_spec.rb +103 -0
  246. data/spec/mongo/operation/write/command/insert_spec.rb +103 -0
  247. data/spec/mongo/operation/write/command/update_spec.rb +109 -0
  248. data/spec/mongo/operation/write/create_index_spec.rb +63 -0
  249. data/spec/mongo/operation/write/create_user_spec.rb +44 -0
  250. data/spec/mongo/operation/write/delete_spec.rb +186 -0
  251. data/spec/mongo/operation/write/drop_index_spec.rb +51 -0
  252. data/spec/mongo/operation/write/insert_spec.rb +244 -0
  253. data/spec/mongo/operation/write/remove_user_spec.rb +46 -0
  254. data/spec/mongo/operation/write/response_spec.rb +85 -0
  255. data/spec/mongo/operation/write/update_spec.rb +228 -0
  256. data/spec/mongo/protocol/delete_spec.rb +167 -0
  257. data/spec/mongo/protocol/get_more_spec.rb +146 -0
  258. data/spec/mongo/protocol/insert_spec.rb +161 -0
  259. data/spec/mongo/protocol/kill_cursors_spec.rb +101 -0
  260. data/spec/mongo/protocol/query_spec.rb +285 -0
  261. data/spec/mongo/protocol/reply_spec.rb +157 -0
  262. data/spec/mongo/protocol/update_spec.rb +186 -0
  263. data/spec/mongo/server/connection_pool/queue_spec.rb +170 -0
  264. data/spec/mongo/server/connection_pool_spec.rb +120 -0
  265. data/spec/mongo/server/connection_spec.rb +312 -0
  266. data/spec/mongo/server/description/features_spec.rb +138 -0
  267. data/spec/mongo/server/description/inspector/primary_elected_spec.rb +94 -0
  268. data/spec/mongo/server/description/inspector/server_added_spec.rb +92 -0
  269. data/spec/mongo/server/description/inspector/server_removed_spec.rb +95 -0
  270. data/spec/mongo/server/description_spec.rb +510 -0
  271. data/spec/mongo/server/monitor_spec.rb +144 -0
  272. data/spec/mongo/server_discovery_and_monitoring_spec.rb +103 -0
  273. data/spec/mongo/server_selection_rtt_spec.rb +104 -0
  274. data/spec/mongo/server_selection_spec.rb +89 -0
  275. data/spec/mongo/server_selector/nearest_spec.rb +250 -0
  276. data/spec/mongo/server_selector/primary_preferred_spec.rb +290 -0
  277. data/spec/mongo/server_selector/primary_spec.rb +114 -0
  278. data/spec/mongo/server_selector/secondary_preferred_spec.rb +252 -0
  279. data/spec/mongo/server_selector/secondary_spec.rb +196 -0
  280. data/spec/mongo/server_selector_spec.rb +101 -0
  281. data/spec/mongo/server_spec.rb +131 -0
  282. data/spec/mongo/uri_spec.rb +517 -0
  283. data/spec/mongo/write_concern/acknowledged_spec.rb +44 -0
  284. data/spec/mongo/write_concern/unacknowledged_spec.rb +15 -0
  285. data/spec/spec_helper.rb +133 -0
  286. data/spec/support/authorization.rb +247 -0
  287. data/spec/support/crud/read.rb +144 -0
  288. data/spec/support/crud/write.rb +214 -0
  289. data/spec/support/crud.rb +203 -0
  290. data/spec/support/crud_tests/read/aggregate.yml +43 -0
  291. data/spec/support/crud_tests/read/count.yml +37 -0
  292. data/spec/support/crud_tests/read/distinct.yml +33 -0
  293. data/spec/support/crud_tests/read/find.yml +50 -0
  294. data/spec/support/crud_tests/write/deleteMany.yml +36 -0
  295. data/spec/support/crud_tests/write/deleteOne.yml +49 -0
  296. data/spec/support/crud_tests/write/findOneAndDelete.yml +54 -0
  297. data/spec/support/crud_tests/write/findOneAndReplace.yml +153 -0
  298. data/spec/support/crud_tests/write/findOneAndUpdate.yml +161 -0
  299. data/spec/support/crud_tests/write/insertMany.yml +24 -0
  300. data/spec/support/crud_tests/write/insertOne.yml +19 -0
  301. data/spec/support/crud_tests/write/replaceOne.yml +96 -0
  302. data/spec/support/crud_tests/write/updateMany.yml +83 -0
  303. data/spec/support/crud_tests/write/updateOne.yml +80 -0
  304. data/spec/support/helpers.rb +140 -0
  305. data/spec/support/matchers.rb +37 -0
  306. data/spec/support/sdam/rs/discover_arbiters.yml +41 -0
  307. data/spec/support/sdam/rs/discover_passives.yml +41 -0
  308. data/spec/support/sdam/rs/discover_primary.yml +40 -0
  309. data/spec/support/sdam/rs/discover_secondary.yml +41 -0
  310. data/spec/support/sdam/rs/discovery.yml +195 -0
  311. data/spec/support/sdam/rs/ghost_discovered.yml +39 -0
  312. data/spec/support/sdam/rs/hosts_differ_from_seeds.yml +34 -0
  313. data/spec/support/sdam/rs/member_reconfig.yml +68 -0
  314. data/spec/support/sdam/rs/member_standalone.yml +60 -0
  315. data/spec/support/sdam/rs/new_primary.yml +74 -0
  316. data/spec/support/sdam/rs/new_primary_wrong_set_name.yml +71 -0
  317. data/spec/support/sdam/rs/non_rs_member.yml +31 -0
  318. data/spec/support/sdam/rs/normalize_case.yml +49 -0
  319. data/spec/support/sdam/rs/primary_becomes_standalone.yml +52 -0
  320. data/spec/support/sdam/rs/primary_changes_set_name.yml +57 -0
  321. data/spec/support/sdam/rs/primary_disconnect.yml +56 -0
  322. data/spec/support/sdam/rs/primary_wrong_set_name.yml +27 -0
  323. data/spec/support/sdam/rs/response_from_removed.yml +63 -0
  324. data/spec/support/sdam/rs/rsother_discovered.yml +41 -0
  325. data/spec/support/sdam/rs/sec_not_auth.yml +49 -0
  326. data/spec/support/sdam/rs/secondary_wrong_set_name.yml +28 -0
  327. data/spec/support/sdam/rs/secondary_wrong_set_name_with_primary.yml +69 -0
  328. data/spec/support/sdam/rs/unexpected_mongos.yml +26 -0
  329. data/spec/support/sdam/rs/wrong_set_name.yml +35 -0
  330. data/spec/support/sdam/sharded/multiple_mongoses.yml +46 -0
  331. data/spec/support/sdam/sharded/non_mongos_removed.yml +41 -0
  332. data/spec/support/sdam/sharded/normalize_uri_case.yml +32 -0
  333. data/spec/support/sdam/single/direct_connection_external_ip.yml +34 -0
  334. data/spec/support/sdam/single/direct_connection_mongos.yml +33 -0
  335. data/spec/support/sdam/single/direct_connection_rsarbiter.yml +35 -0
  336. data/spec/support/sdam/single/direct_connection_rsprimary.yml +34 -0
  337. data/spec/support/sdam/single/direct_connection_rssecondary.yml +35 -0
  338. data/spec/support/sdam/single/direct_connection_slave.yml +32 -0
  339. data/spec/support/sdam/single/direct_connection_standalone.yml +32 -0
  340. data/spec/support/sdam/single/not_ok_response.yml +39 -0
  341. data/spec/support/sdam/single/standalone_removed.yml +32 -0
  342. data/spec/support/sdam/single/unavailable_seed.yml +28 -0
  343. data/spec/support/server_discovery_and_monitoring.rb +167 -0
  344. data/spec/support/server_selection/rtt/first_value.yml +4 -0
  345. data/spec/support/server_selection/rtt/first_value_zero.yml +4 -0
  346. data/spec/support/server_selection/rtt/value_test_1.yml +4 -0
  347. data/spec/support/server_selection/rtt/value_test_2.yml +4 -0
  348. data/spec/support/server_selection/rtt/value_test_3.yml +4 -0
  349. data/spec/support/server_selection/rtt/value_test_4.yml +4 -0
  350. data/spec/support/server_selection/rtt/value_test_5.yml +4 -0
  351. data/spec/support/server_selection/selection/ReplicaSetNoPrimary/read/Nearest.yml +26 -0
  352. data/spec/support/server_selection/selection/ReplicaSetNoPrimary/read/Nearest_non_matching.yml +21 -0
  353. data/spec/support/server_selection/selection/ReplicaSetNoPrimary/read/Primary.yml +21 -0
  354. data/spec/support/server_selection/selection/ReplicaSetNoPrimary/read/PrimaryPreferred.yml +26 -0
  355. data/spec/support/server_selection/selection/ReplicaSetNoPrimary/read/PrimaryPreferred_non_matching.yml +21 -0
  356. data/spec/support/server_selection/selection/ReplicaSetNoPrimary/read/Secondary.yml +26 -0
  357. data/spec/support/server_selection/selection/ReplicaSetNoPrimary/read/SecondaryPreferred.yml +26 -0
  358. data/spec/support/server_selection/selection/ReplicaSetNoPrimary/read/SecondaryPreferred_non_matching.yml +21 -0
  359. data/spec/support/server_selection/selection/ReplicaSetNoPrimary/read/Secondary_non_matching.yml +21 -0
  360. data/spec/support/server_selection/selection/ReplicaSetWithPrimary/read/Nearest.yml +33 -0
  361. data/spec/support/server_selection/selection/ReplicaSetWithPrimary/read/Nearest_non_matching.yml +26 -0
  362. data/spec/support/server_selection/selection/ReplicaSetWithPrimary/read/Primary.yml +29 -0
  363. data/spec/support/server_selection/selection/ReplicaSetWithPrimary/read/PrimaryPreferred.yml +29 -0
  364. data/spec/support/server_selection/selection/ReplicaSetWithPrimary/read/PrimaryPreferred_non_matching.yml +29 -0
  365. data/spec/support/server_selection/selection/ReplicaSetWithPrimary/read/Secondary.yml +31 -0
  366. data/spec/support/server_selection/selection/ReplicaSetWithPrimary/read/SecondaryPreferred.yml +31 -0
  367. data/spec/support/server_selection/selection/ReplicaSetWithPrimary/read/SecondaryPreferred_non_matching.yml +29 -0
  368. data/spec/support/server_selection/selection/ReplicaSetWithPrimary/read/Secondary_non_matching.yml +26 -0
  369. data/spec/support/server_selection/selection/Sharded/read/SecondaryPreferred.yml +26 -0
  370. data/spec/support/server_selection/selection/Single/read/SecondaryPreferred.yml +19 -0
  371. data/spec/support/server_selection/selection/Unknown/read/SecondaryPreferred.yml +11 -0
  372. data/spec/support/server_selection.rb +157 -0
  373. data/spec/support/server_selection_rtt.rb +41 -0
  374. data/spec/support/shared/bulk_write.rb +535 -0
  375. data/spec/support/shared/cursor.rb +38 -0
  376. data/spec/support/shared/operation.rb +77 -0
  377. data/spec/support/shared/protocol.rb +31 -0
  378. data/spec/support/shared/server_selector.rb +111 -0
  379. data/spec/support/shared/socket.rb +82 -0
  380. data/spec/support/travis.rb +14 -0
  381. data.tar.gz.sig +2 -3
  382. metadata +583 -186
  383. metadata.gz.sig +0 -0
  384. data/VERSION +0 -1
  385. data/lib/mongo/bulk_write_collection_view.rb +0 -387
  386. data/lib/mongo/collection_writer.rb +0 -364
  387. data/lib/mongo/connection/node.rb +0 -249
  388. data/lib/mongo/connection/pool.rb +0 -340
  389. data/lib/mongo/connection/pool_manager.rb +0 -320
  390. data/lib/mongo/connection/sharding_pool_manager.rb +0 -67
  391. data/lib/mongo/connection/socket/ssl_socket.rb +0 -95
  392. data/lib/mongo/connection/socket/tcp_socket.rb +0 -87
  393. data/lib/mongo/connection/socket/unix_socket.rb +0 -39
  394. data/lib/mongo/db.rb +0 -808
  395. data/lib/mongo/exception.rb +0 -145
  396. data/lib/mongo/functional/authentication.rb +0 -455
  397. data/lib/mongo/functional/logging.rb +0 -85
  398. data/lib/mongo/functional/read_preference.rb +0 -183
  399. data/lib/mongo/functional/scram.rb +0 -556
  400. data/lib/mongo/functional/uri_parser.rb +0 -409
  401. data/lib/mongo/functional/write_concern.rb +0 -66
  402. data/lib/mongo/gridfs/grid.rb +0 -112
  403. data/lib/mongo/gridfs/grid_ext.rb +0 -53
  404. data/lib/mongo/gridfs/grid_file_system.rb +0 -163
  405. data/lib/mongo/gridfs/grid_io.rb +0 -484
  406. data/lib/mongo/legacy.rb +0 -140
  407. data/lib/mongo/mongo_client.rb +0 -697
  408. data/lib/mongo/mongo_replica_set_client.rb +0 -535
  409. data/lib/mongo/mongo_sharded_client.rb +0 -159
  410. data/lib/mongo/networking.rb +0 -372
  411. data/lib/mongo/utils/conversions.rb +0 -110
  412. data/lib/mongo/utils/core_ext.rb +0 -70
  413. data/lib/mongo/utils/server_version.rb +0 -69
  414. data/lib/mongo/utils/support.rb +0 -80
  415. data/test/functional/authentication_test.rb +0 -39
  416. data/test/functional/bulk_api_stress_test.rb +0 -133
  417. data/test/functional/bulk_write_collection_view_test.rb +0 -1198
  418. data/test/functional/client_test.rb +0 -627
  419. data/test/functional/collection_test.rb +0 -2175
  420. data/test/functional/collection_writer_test.rb +0 -83
  421. data/test/functional/conversions_test.rb +0 -163
  422. data/test/functional/cursor_fail_test.rb +0 -57
  423. data/test/functional/cursor_message_test.rb +0 -56
  424. data/test/functional/cursor_test.rb +0 -683
  425. data/test/functional/db_api_test.rb +0 -835
  426. data/test/functional/db_test.rb +0 -348
  427. data/test/functional/grid_file_system_test.rb +0 -285
  428. data/test/functional/grid_io_test.rb +0 -252
  429. data/test/functional/grid_test.rb +0 -273
  430. data/test/functional/pool_test.rb +0 -136
  431. data/test/functional/safe_test.rb +0 -98
  432. data/test/functional/support_test.rb +0 -62
  433. data/test/functional/timeout_test.rb +0 -60
  434. data/test/functional/uri_test.rb +0 -446
  435. data/test/functional/write_concern_test.rb +0 -118
  436. data/test/helpers/general.rb +0 -50
  437. data/test/helpers/test_unit.rb +0 -476
  438. data/test/replica_set/authentication_test.rb +0 -37
  439. data/test/replica_set/basic_test.rb +0 -189
  440. data/test/replica_set/client_test.rb +0 -393
  441. data/test/replica_set/connection_test.rb +0 -138
  442. data/test/replica_set/count_test.rb +0 -66
  443. data/test/replica_set/cursor_test.rb +0 -220
  444. data/test/replica_set/insert_test.rb +0 -157
  445. data/test/replica_set/max_values_test.rb +0 -151
  446. data/test/replica_set/pinning_test.rb +0 -105
  447. data/test/replica_set/query_test.rb +0 -73
  448. data/test/replica_set/read_preference_test.rb +0 -219
  449. data/test/replica_set/refresh_test.rb +0 -211
  450. data/test/replica_set/replication_ack_test.rb +0 -95
  451. data/test/sharded_cluster/basic_test.rb +0 -203
  452. data/test/shared/authentication/basic_auth_shared.rb +0 -260
  453. data/test/shared/authentication/bulk_api_auth_shared.rb +0 -249
  454. data/test/shared/authentication/gssapi_shared.rb +0 -176
  455. data/test/shared/authentication/sasl_plain_shared.rb +0 -96
  456. data/test/shared/authentication/scram_shared.rb +0 -92
  457. data/test/shared/ssl_shared.rb +0 -235
  458. data/test/test_helper.rb +0 -61
  459. data/test/threading/basic_test.rb +0 -120
  460. data/test/tools/mongo_config.rb +0 -708
  461. data/test/tools/mongo_config_test.rb +0 -160
  462. data/test/unit/client_test.rb +0 -381
  463. data/test/unit/collection_test.rb +0 -166
  464. data/test/unit/connection_test.rb +0 -335
  465. data/test/unit/cursor_test.rb +0 -307
  466. data/test/unit/db_test.rb +0 -136
  467. data/test/unit/grid_test.rb +0 -76
  468. data/test/unit/mongo_sharded_client_test.rb +0 -48
  469. data/test/unit/node_test.rb +0 -93
  470. data/test/unit/pool_manager_test.rb +0 -111
  471. data/test/unit/read_pref_test.rb +0 -406
  472. data/test/unit/read_test.rb +0 -159
  473. data/test/unit/safe_test.rb +0 -158
  474. data/test/unit/sharding_pool_manager_test.rb +0 -84
  475. data/test/unit/write_concern_test.rb +0 -175
@@ -0,0 +1,159 @@
1
+ # Copyright (C) 2014-2015 MongoDB Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require 'mongo/auth/user/view'
16
+
17
+ module Mongo
18
+ module Auth
19
+
20
+ # Represents a user in MongoDB.
21
+ #
22
+ # @since 2.0.0
23
+ class User
24
+
25
+ # The users collection for the database.
26
+ #
27
+ # @since 2.0.0
28
+ COLLECTION = 'system.users'.freeze
29
+
30
+ # @return [ String ] The authorization source, either a database or
31
+ # external name.
32
+ attr_reader :auth_source
33
+
34
+ # @return [ String ] The database the user is created in.
35
+ attr_reader :database
36
+
37
+ # @return [ Hash ] The authentication mechanism properties.
38
+ attr_reader :auth_mech_properties
39
+
40
+ # @return [ Symbol ] The authorization mechanism.
41
+ attr_reader :mechanism
42
+
43
+ # @return [ String ] The username.
44
+ attr_reader :name
45
+
46
+ # @return [ String ] The cleartext password.
47
+ attr_reader :password
48
+
49
+ # @return [ Array<String> ] roles The user roles.
50
+ attr_reader :roles
51
+
52
+ # Determine if this user is equal to another.
53
+ #
54
+ # @example Check user equality.
55
+ # user == other
56
+ #
57
+ # @param [ Object ] other The object to compare against.
58
+ #
59
+ # @return [ true, false ] If the objects are equal.
60
+ #
61
+ # @since 2.0.0
62
+ def ==(other)
63
+ return false unless other.is_a?(User)
64
+ name == other.name && database == other.database && password == other.password
65
+ end
66
+
67
+ # Get an authentication key for the user based on a nonce from the
68
+ # server.
69
+ #
70
+ # @example Get the authentication key.
71
+ # user.auth_key(nonce)
72
+ #
73
+ # @param [ String ] nonce The response from the server.
74
+ #
75
+ # @return [ String ] The authentication key.
76
+ #
77
+ # @since 2.0.0
78
+ def auth_key(nonce)
79
+ Digest::MD5.hexdigest("#{nonce}#{name}#{hashed_password}")
80
+ end
81
+
82
+ # Get the UTF-8 encoded name with escaped special characters for use with
83
+ # SCRAM authorization.
84
+ #
85
+ # @example Get the encoded name.
86
+ # user.encoded_name
87
+ #
88
+ # @return [ String ] The encoded user name.
89
+ #
90
+ # @since 2.0.0
91
+ def encoded_name
92
+ name.encode(BSON::UTF8).gsub('=','=3D').gsub(',','=2C')
93
+ end
94
+
95
+ # Get the hash key for the user.
96
+ #
97
+ # @example Get the hash key.
98
+ # user.hash
99
+ #
100
+ # @return [ String ] The user hash key.
101
+ #
102
+ # @since 2.0.0
103
+ def hash
104
+ [ name, database, password ].hash
105
+ end
106
+
107
+ # Get the user's hashed password.
108
+ #
109
+ # @example Get the user's hashed password.
110
+ # user.hashed_password
111
+ #
112
+ # @return [ String ] The hashed password.
113
+ #
114
+ # @since 2.0.0
115
+ def hashed_password
116
+ @hashed_password ||= Digest::MD5.hexdigest("#{name}:mongo:#{password}").encode(BSON::UTF8)
117
+ end
118
+
119
+ # Create the new user.
120
+ #
121
+ # @example Create a new user.
122
+ # Mongo::Auth::User.new(options)
123
+ #
124
+ # @param [ Hash ] options The options to create the user from.
125
+ #
126
+ # @option options [ String ] :auth_source The authorization database or
127
+ # external source.
128
+ # @option options [ String ] :database The database the user is
129
+ # authorized for.
130
+ # @option options [ String ] :user The user name.
131
+ # @option options [ String ] :password The user's password.
132
+ # @option options [ Symbol ] :auth_mech The authorization mechanism.
133
+ # @option options [ Array<String>, Array<Hash> ] roles The user roles.
134
+ #
135
+ # @since 2.0.0
136
+ def initialize(options)
137
+ @auth_source = options[:auth_source] || options[:database] || Database::ADMIN
138
+ @database = options[:database] || Database::ADMIN
139
+ @name = options[:user]
140
+ @password = options[:password] || options[:pwd]
141
+ @mechanism = options[:auth_mech] || :mongodb_cr
142
+ @auth_mech_properties = options[:auth_mech_properties] || {}
143
+ @roles = options[:roles] || []
144
+ end
145
+
146
+ # Get the specification for the user, used in creation.
147
+ #
148
+ # @example Get the user's specification.
149
+ # user.spec
150
+ #
151
+ # @return [ Hash ] The user spec.
152
+ #
153
+ # @since 2.0.0
154
+ def spec
155
+ { pwd: hashed_password, roles: roles }
156
+ end
157
+ end
158
+ end
159
+ end
@@ -0,0 +1,92 @@
1
+ # Copyright (C) 2014 MongoDB Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module Mongo
16
+ module Auth
17
+ class X509
18
+
19
+ # Defines behaviour around a single x.509 conversation between the
20
+ # client and server.
21
+ #
22
+ # @since 2.0.0
23
+ class Conversation
24
+
25
+ # The login message.
26
+ #
27
+ # @since 2.0.0
28
+ LOGIN = { authenticate: 1 }.freeze
29
+
30
+ # @return [ Protocol::Reply ] reply The current reply in the
31
+ # conversation.
32
+ attr_reader :reply
33
+
34
+ # @return [ User ] user The user for the conversation.
35
+ attr_reader :user
36
+
37
+ # Finalize the x.509 conversation. This is meant to be iterated until
38
+ # the provided reply indicates the conversation is finished.
39
+ #
40
+ # @example Finalize the conversation.
41
+ # conversation.finalize(reply)
42
+ #
43
+ # @param [ Protocol::Reply ] reply The reply of the previous
44
+ # message.
45
+ #
46
+ # @return [ Protocol::Query ] The next message to send.
47
+ #
48
+ # @since 2.0.0
49
+ def finalize(reply)
50
+ validate!(reply)
51
+ end
52
+
53
+ # Start the x.509 conversation. This returns the first message that
54
+ # needs to be send to the server.
55
+ #
56
+ # @example Start the conversation.
57
+ # conversation.start
58
+ #
59
+ # @return [ Protocol::Query ] The first x.509 conversation message.
60
+ #
61
+ # @since 2.0.0
62
+ def start
63
+ Protocol::Query.new(
64
+ Auth::EXTERNAL,
65
+ Database::COMMAND,
66
+ LOGIN.merge(user: user.name, mechanism: X509::MECHANISM),
67
+ limit: -1
68
+ )
69
+ end
70
+
71
+ # Create the new conversation.
72
+ #
73
+ # @example Create the new coversation.
74
+ # Conversation.new(user, "admin")
75
+ #
76
+ # @param [ Auth::User ] user The user to converse about.
77
+ #
78
+ # @since 2.0.0
79
+ def initialize(user)
80
+ @user = user
81
+ end
82
+
83
+ private
84
+
85
+ def validate!(reply)
86
+ raise Unauthorized.new(user) if reply.documents[0]['ok'] != 1
87
+ @reply = reply
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,48 @@
1
+ # Copyright (C) 2014-2015 MongoDB Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require 'mongo/auth/x509/conversation'
16
+
17
+ module Mongo
18
+ module Auth
19
+
20
+ # Defines behaviour for x.509 authentication.
21
+ #
22
+ # @since 2.0.0
23
+ class X509
24
+ include Executable
25
+
26
+ # The authentication mechinism string.
27
+ #
28
+ # @since 2.0.0
29
+ MECHANISM = 'MONGODB-X509'.freeze
30
+
31
+ # Log the user in on the given connection.
32
+ #
33
+ # @example Log the user in.
34
+ # user.login(connection)
35
+ #
36
+ # @param [ Mongo::Connection ] connection The connection to log into.
37
+ # on.
38
+ #
39
+ # @return [ Protocol::Reply ] The authentication response.
40
+ #
41
+ # @since 2.0.0
42
+ def login(connection)
43
+ conversation = Conversation.new(user)
44
+ conversation.finalize(connection.dispatch([ conversation.start ]))
45
+ end
46
+ end
47
+ end
48
+ end
data/lib/mongo/auth.rb ADDED
@@ -0,0 +1,108 @@
1
+ # Copyright (C) 2014-2015 MongoDB, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require 'mongo/auth/executable'
16
+ require 'mongo/auth/cr'
17
+ require 'mongo/auth/ldap'
18
+ require 'mongo/auth/scram'
19
+ require 'mongo/auth/user'
20
+ require 'mongo/auth/x509'
21
+ require 'mongo/auth/roles'
22
+
23
+ module Mongo
24
+
25
+ # This namespace contains all authentication related behaviour.
26
+ #
27
+ # @since 2.0.0
28
+ module Auth
29
+ extend self
30
+
31
+ # The external database name.
32
+ #
33
+ # @since 2.0.0
34
+ EXTERNAL = '$external'.freeze
35
+
36
+ # Constant for the nonce command.
37
+ #
38
+ # @since 2.0.0
39
+ GET_NONCE = { getnonce: 1 }.freeze
40
+
41
+ # Constant for the nonce field.
42
+ #
43
+ # @since 2.0.0
44
+ NONCE = 'nonce'.freeze
45
+
46
+ # Map the symbols parsed from the URI connection string to strategies.
47
+ #
48
+ # @since 2.0.0
49
+ SOURCES = {
50
+ mongodb_cr: CR,
51
+ mongodb_x509: X509,
52
+ plain: LDAP,
53
+ scram: SCRAM
54
+ }
55
+
56
+ # Get the authorization strategy for the provided auth mechanism.
57
+ #
58
+ # @example Get the strategy.
59
+ # Auth.get(user)
60
+ #
61
+ # @param [ Auth::User ] user The user object.
62
+ #
63
+ # @return [ CR, X509, LDAP, Kerberos ] The auth strategy.
64
+ #
65
+ # @since 2.0.0
66
+ def get(user)
67
+ mechanism = user.mechanism
68
+ raise InvalidMechanism.new(mechanism) if !SOURCES.has_key?(mechanism)
69
+ SOURCES[mechanism].new(user)
70
+ end
71
+
72
+ # Raised when trying to get an invalid authorization mechanism.
73
+ #
74
+ # @since 2.0.0
75
+ class InvalidMechanism < RuntimeError
76
+
77
+ # Instantiate the new error.
78
+ #
79
+ # @example Instantiate the error.
80
+ # Mongo::Auth::InvalidMechanism.new(:test)
81
+ #
82
+ # @param [ Symbol ] mechanism The provided mechanism.
83
+ #
84
+ # @since 2.0.0
85
+ def initialize(mechanism)
86
+ super("#{mechanism.inspect} is invalid, please use mongodb_cr, mongodb_x509, gssapi or plain.")
87
+ end
88
+ end
89
+
90
+ # Raised when a user is not authorized on a database.
91
+ #
92
+ # @since 2.0.0
93
+ class Unauthorized < RuntimeError
94
+
95
+ # Instantiate the new error.
96
+ #
97
+ # @example Instantiate the error.
98
+ # Mongo::Auth::Unauthorized.new(user)
99
+ #
100
+ # @param [ Mongo::Auth::User ] user The unauthorized user.
101
+ #
102
+ # @since 2.0.0
103
+ def initialize(user)
104
+ super("User #{user.name} is not authorized to access #{user.database}.")
105
+ end
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,191 @@
1
+ # Copyright (C) 2014-2015 MongoDB, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require 'mongo/bulk_write/insertable'
16
+ require 'mongo/bulk_write/deletable'
17
+ require 'mongo/bulk_write/updatable'
18
+ require 'mongo/bulk_write/replacable'
19
+
20
+ module Mongo
21
+ module BulkWrite
22
+
23
+ # Defines shared behaviour between ordered and unordered bulk operations.
24
+ #
25
+ # @since 2.0.0
26
+ module BulkWritable
27
+ include Insertable
28
+ include Deletable
29
+ include Updatable
30
+ include Replacable
31
+ extend Forwardable
32
+
33
+ # Delegate various methods to the collection.
34
+ def_delegators :@collection, :database, :cluster, :next_primary
35
+
36
+ # The fields contained in the result document returned from executing the
37
+ # operations.
38
+ #
39
+ # @since 2.0.0.
40
+ RESULT_FIELDS = [ :n_inserted,
41
+ :n_removed,
42
+ :n_modified,
43
+ :n_upserted,
44
+ :n_matched ]
45
+
46
+
47
+ # Initialize a bulk write object.
48
+ #
49
+ # @example Initialize a bulk write object.
50
+ # Mongo::BulkWrite::OrderedBulkWrite.new(collection, operations, options)
51
+ # Mongo::BulkWrite::UnorderedBulkWrite.new(collection, operations, options)
52
+ #
53
+ # @param [ Mongo::Collection ] collection The collection the operations will
54
+ # be executed on.
55
+ # @param [ Array<Hash> ] operations The operations to be executed.
56
+ # @param [ Hash ] options The options.
57
+ #
58
+ # @option options [ Hash ] :write_concern The write concern to use for this
59
+ # bulk write.
60
+ #
61
+ # @since 2.0.0
62
+ def initialize(collection, operations, options)
63
+ @collection = collection
64
+ @operations = operations
65
+ @options = options
66
+ end
67
+
68
+ # Execute the bulk operations.
69
+ #
70
+ # @example Execute the operations.
71
+ # bulk.execute
72
+ #
73
+ # @return [ Hash ] The results from the bulk write.
74
+ #
75
+ # @since 2.0.0
76
+ def execute
77
+ server = next_primary
78
+ validate_operations!
79
+ merged_ops.each do |op|
80
+ validate_type!(op.keys.first)
81
+ execute_op(op, server)
82
+ end
83
+ finalize
84
+ end
85
+
86
+ private
87
+
88
+ def write_concern
89
+ @write_concern ||= WriteConcern.get(@options[:write_concern]) ||
90
+ @collection.write_concern
91
+ end
92
+
93
+ def validate_operations!
94
+ unless @operations && @operations.size > 0
95
+ raise ArgumentError.new('Operations cannot be empty')
96
+ end
97
+ end
98
+
99
+ def validate_type!(type)
100
+ unless respond_to?(type, true)
101
+ raise Error::InvalidBulkOperationType.new(type)
102
+ end
103
+ end
104
+
105
+ def max_write_batches(op, server)
106
+ type = op.keys.first
107
+ ops = []
108
+ while op[type].size > server.max_write_batch_size
109
+ ops << { type => op[type].shift(server.max_write_batch_size),
110
+ :indexes => op[:indexes].shift(server.max_write_batch_size) }
111
+ end
112
+ ops << op
113
+ end
114
+
115
+ def split(op, type)
116
+ n = op[type].size/2
117
+ [ { type => op[type].shift(n),
118
+ :indexes => op[:indexes].shift(n) },
119
+ { type => op[type],
120
+ :indexes => op[:indexes] }
121
+ ]
122
+ end
123
+
124
+ def execute_op(operation, server)
125
+ ops = max_write_batches(operation, server)
126
+
127
+ until ops.empty?
128
+ op = ops.shift
129
+ type = op.keys.first
130
+ begin
131
+ process(send(type, op, server), op[:indexes])
132
+ rescue Error::MaxBSONSize, Error::MaxMessageSize => ex
133
+ raise ex if op[type].size < 2
134
+ ops = split(op, type) + ops
135
+ end
136
+ end
137
+ end
138
+
139
+ def merge_consecutive_ops(ops)
140
+ ops.each_with_index.inject([]) do |merged, (op, i)|
141
+ type = op.keys.first
142
+ op[:indexes] ||= [ i ]
143
+ previous = merged.last
144
+ if previous && previous.keys.first == type
145
+ merged[-1].merge!(type => previous[type] << op[type],
146
+ :indexes => previous[:indexes] + op[:indexes])
147
+ merged
148
+ else
149
+ merged << { type => [ op[type] ].flatten,
150
+ :indexes => op[:indexes] }
151
+ end
152
+ end
153
+ end
154
+
155
+ def merge_ops_by_type
156
+ indexes = {}
157
+ ops_hash = @operations.each_with_index.inject({}) do |merged, (op, i)|
158
+ type = op.keys.first
159
+ merged.merge!(op) { |type, v1, v2| ([v1] << v2).flatten }
160
+ indexes[type] = (indexes[type] || []).push(i)
161
+ merged
162
+ end
163
+ ops_hash.keys.reduce([]) do |ops_list, type|
164
+ ops_list << { type => ops_hash[type], :indexes => indexes[type] }
165
+ end
166
+ end
167
+
168
+ def combine_results(result, indexes)
169
+ @results ||= {}
170
+ write_errors = result.aggregate_write_errors(indexes)
171
+
172
+ # The Bulk API only returns the first write concern error encountered.
173
+ @write_concern_errors ||= result.aggregate_write_concern_errors(indexes)
174
+
175
+ @results.tap do |results|
176
+ RESULT_FIELDS.each do |field|
177
+ results.merge!(
178
+ field => (results[field] || 0) + result.send(field)
179
+ ) if result.respond_to?(field)
180
+ end
181
+
182
+ results.merge!(
183
+ write_errors: ((results[:write_errors] || []) << write_errors).flatten
184
+ ) if write_errors
185
+
186
+ results.merge!(write_concern_errors: @write_concern_errors) if @write_concern_errors
187
+ end
188
+ end
189
+ end
190
+ end
191
+ end
@@ -0,0 +1,60 @@
1
+ # Copyright (C) 2014-2015 MongoDB, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module Mongo
16
+ module BulkWrite
17
+
18
+ # Defines behavior for validating and combining delete bulk write operations.
19
+ #
20
+ # @since 2.0.0.
21
+ module Deletable
22
+
23
+ private
24
+
25
+ def valid_doc?(doc)
26
+ doc.respond_to?(:keys)
27
+ end
28
+
29
+ def validate_delete_op!(type, d)
30
+ raise Error::InvalidBulkOperation.new(type, d) unless valid_doc?(d)
31
+ end
32
+
33
+ def deletes(ops, type)
34
+ limit = (type == :delete_one) ? 1 : 0
35
+ ops.collect do |d|
36
+ validate_delete_op!(type, d)
37
+ { q: d, limit: limit }
38
+ end
39
+ end
40
+
41
+ def delete(ops, type, server)
42
+ Operation::Write::BulkDelete.new(
43
+ :deletes => deletes(ops, type),
44
+ :db_name => database.name,
45
+ :coll_name => @collection.name,
46
+ :write_concern => write_concern,
47
+ :ordered => ordered?
48
+ ).execute(server.context)
49
+ end
50
+
51
+ def delete_one(op, server)
52
+ delete(op[:delete_one], __method__, server)
53
+ end
54
+
55
+ def delete_many(op, server)
56
+ delete(op[:delete_many], __method__, server)
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,52 @@
1
+ # Copyright (C) 2014-2015 MongoDB, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module Mongo
16
+ module BulkWrite
17
+
18
+ # Defines behavior for validating and combining insert bulk write operations.
19
+ #
20
+ # @since 2.0.0.
21
+ module Insertable
22
+
23
+ private
24
+
25
+ def valid_doc?(doc)
26
+ doc.respond_to?(:keys)
27
+ end
28
+
29
+ def validate_insert_ops!(type, inserts)
30
+ if inserts.empty?
31
+ raise Error::InvalidBulkOperation.new(type, inserts)
32
+ end
33
+ inserts.each do |i|
34
+ unless valid_doc?(i)
35
+ raise Error::InvalidBulkOperation.new(type, i)
36
+ end
37
+ end
38
+ end
39
+
40
+ def insert_one(op, server)
41
+ validate_insert_ops!(__method__, op[:insert_one])
42
+ Operation::Write::BulkInsert.new(
43
+ :documents => op[:insert_one].flatten,
44
+ :db_name => database.name,
45
+ :coll_name => @collection.name,
46
+ :write_concern => write_concern,
47
+ :ordered => ordered?
48
+ ).execute(server.context)
49
+ end
50
+ end
51
+ end
52
+ end