mongo 1.12.5 → 2.0.0.beta

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 (437) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/CONTRIBUTING.md +64 -0
  5. data/LICENSE +1 -1
  6. data/README.md +23 -125
  7. data/Rakefile +26 -21
  8. data/bin/mongo_console +6 -38
  9. data/lib/mongo.rb +23 -82
  10. data/lib/mongo/address.rb +111 -0
  11. data/lib/mongo/address/ipv4.rb +85 -0
  12. data/lib/mongo/address/ipv6.rb +85 -0
  13. data/lib/mongo/address/unix.rb +76 -0
  14. data/lib/mongo/auth.rb +108 -0
  15. data/lib/mongo/auth/cr.rb +44 -0
  16. data/lib/mongo/auth/cr/conversation.rb +119 -0
  17. data/lib/mongo/auth/executable.rb +52 -0
  18. data/lib/mongo/auth/ldap.rb +48 -0
  19. data/lib/mongo/auth/ldap/conversation.rb +92 -0
  20. data/lib/mongo/auth/roles.rb +104 -0
  21. data/lib/mongo/auth/scram.rb +53 -0
  22. data/lib/mongo/auth/scram/conversation.rb +450 -0
  23. data/lib/mongo/auth/user.rb +159 -0
  24. data/lib/mongo/auth/user/view.rb +102 -0
  25. data/lib/mongo/auth/x509.rb +48 -0
  26. data/lib/mongo/auth/x509/conversation.rb +92 -0
  27. data/lib/mongo/{gridfs.rb → bulk.rb} +2 -5
  28. data/lib/mongo/bulk/bulk_write.rb +307 -0
  29. data/lib/mongo/client.rb +233 -0
  30. data/lib/mongo/cluster.rb +203 -0
  31. data/lib/mongo/cluster/topology.rb +60 -0
  32. data/lib/mongo/cluster/topology/replica_set.rb +160 -0
  33. data/lib/mongo/cluster/topology/sharded.rb +132 -0
  34. data/lib/mongo/cluster/topology/standalone.rb +132 -0
  35. data/lib/mongo/cluster/topology/unknown.rb +155 -0
  36. data/lib/mongo/collection.rb +130 -1101
  37. data/lib/mongo/collection/view.rb +169 -0
  38. data/lib/mongo/collection/view/aggregation.rb +108 -0
  39. data/lib/mongo/collection/view/explainable.rb +49 -0
  40. data/lib/mongo/collection/view/immutable.rb +43 -0
  41. data/lib/mongo/collection/view/iterable.rb +48 -0
  42. data/lib/mongo/collection/view/map_reduce.rb +191 -0
  43. data/lib/mongo/collection/view/readable.rb +363 -0
  44. data/lib/mongo/collection/view/writable.rb +169 -0
  45. data/lib/mongo/cursor.rb +79 -680
  46. data/lib/mongo/database.rb +224 -0
  47. data/lib/mongo/database/view.rb +101 -0
  48. data/lib/mongo/error.rb +81 -0
  49. data/lib/mongo/error/bulk_write_failure.rb +41 -0
  50. data/lib/mongo/{utils/thread_local_variable_manager.rb → error/empty_batch.rb} +22 -8
  51. data/{test/functional/db_connection_test.rb → lib/mongo/error/invalid_bulk_operation.rb} +19 -8
  52. data/lib/mongo/error/invalid_collection_name.rb +39 -0
  53. data/lib/mongo/error/invalid_database_name.rb +39 -0
  54. data/{test/replica_set/ssl_test.rb → lib/mongo/error/invalid_document.rb} +21 -14
  55. data/lib/mongo/error/invalid_file.rb +38 -0
  56. data/lib/mongo/error/invalid_nonce.rb +46 -0
  57. data/lib/mongo/error/invalid_replacement_document.rb +39 -0
  58. data/lib/mongo/error/invalid_signature.rb +47 -0
  59. data/{test/functional/ssl_test.rb → lib/mongo/error/invalid_update_document.rb} +22 -12
  60. data/lib/mongo/error/max_bson_size.rb +40 -0
  61. data/lib/mongo/error/max_message_size.rb +42 -0
  62. data/lib/mongo/{utils.rb → error/need_primary_server.rb} +10 -6
  63. data/lib/mongo/{connection.rb → error/operation_failure.rb} +10 -6
  64. data/lib/mongo/error/parser.rb +77 -0
  65. data/lib/mongo/{connection/socket.rb → error/socket_error.rb} +10 -5
  66. data/lib/mongo/error/socket_timeout_error.rb +23 -0
  67. data/lib/mongo/error/unsupported_features.rb +43 -0
  68. data/lib/mongo/event.rb +40 -0
  69. data/lib/mongo/event/listeners.rb +63 -0
  70. data/lib/mongo/event/primary_elected.rb +53 -0
  71. data/lib/mongo/event/publisher.rb +42 -0
  72. data/lib/mongo/event/server_added.rb +53 -0
  73. data/lib/mongo/event/server_removed.rb +53 -0
  74. data/lib/mongo/event/subscriber.rb +41 -0
  75. data/lib/mongo/grid.rb +16 -0
  76. data/lib/mongo/grid/file.rb +94 -0
  77. data/lib/mongo/grid/file/chunk.rb +184 -0
  78. data/lib/mongo/grid/file/metadata.rb +223 -0
  79. data/lib/mongo/grid/fs.rb +149 -0
  80. data/lib/mongo/index.rb +64 -0
  81. data/lib/mongo/index/view.rb +205 -0
  82. data/lib/mongo/loggable.rb +126 -0
  83. data/lib/mongo/logger.rb +132 -0
  84. data/lib/mongo/operation.rb +26 -0
  85. data/lib/mongo/operation/aggregate.rb +100 -0
  86. data/lib/mongo/operation/aggregate/result.rb +84 -0
  87. data/lib/mongo/operation/batchable.rb +103 -0
  88. data/lib/mongo/operation/bulk_delete/result.rb +197 -0
  89. data/lib/mongo/operation/bulk_insert/result.rb +195 -0
  90. data/lib/mongo/operation/bulk_update/result.rb +295 -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 +116 -0
  96. data/lib/mongo/operation/list_indexes/result.rb +118 -0
  97. data/lib/mongo/operation/map_reduce.rb +96 -0
  98. data/lib/mongo/operation/map_reduce/result.rb +122 -0
  99. data/lib/mongo/{functional.rb → operation/read.rb} +7 -7
  100. data/lib/mongo/operation/read/collections_info.rb +67 -0
  101. data/lib/mongo/operation/read/get_more.rb +71 -0
  102. data/lib/mongo/operation/read/indexes.rb +68 -0
  103. data/lib/mongo/operation/read/list_collections.rb +75 -0
  104. data/lib/mongo/operation/read/list_indexes.rb +77 -0
  105. data/lib/mongo/operation/read/query.rb +71 -0
  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 +380 -0
  109. data/lib/mongo/operation/write.rb +25 -0
  110. data/lib/mongo/operation/write/bulk_delete.rb +158 -0
  111. data/lib/mongo/operation/write/bulk_insert.rb +160 -0
  112. data/lib/mongo/operation/write/bulk_update.rb +167 -0
  113. data/lib/mongo/{connection/socket/socket_util.rb → operation/write/command.rb} +9 -24
  114. data/lib/mongo/operation/write/command/create_user.rb +43 -0
  115. data/lib/mongo/operation/write/command/delete.rb +56 -0
  116. data/lib/mongo/operation/write/command/drop_index.rb +51 -0
  117. data/lib/mongo/operation/write/command/ensure_index.rb +55 -0
  118. data/lib/mongo/operation/write/command/insert.rb +55 -0
  119. data/lib/mongo/operation/write/command/remove_user.rb +42 -0
  120. data/lib/mongo/operation/write/command/update.rb +60 -0
  121. data/lib/mongo/operation/write/command/writable.rb +61 -0
  122. data/lib/mongo/operation/write/create_index.rb +84 -0
  123. data/lib/mongo/operation/write/create_user.rb +75 -0
  124. data/lib/mongo/operation/write/delete.rb +91 -0
  125. data/lib/mongo/operation/write/drop_index.rb +62 -0
  126. data/lib/mongo/operation/write/insert.rb +88 -0
  127. data/lib/mongo/operation/write/remove_user.rb +70 -0
  128. data/lib/mongo/operation/write/update.rb +98 -0
  129. data/lib/mongo/protocol.rb +15 -0
  130. data/lib/mongo/protocol/bit_vector.rb +61 -0
  131. data/lib/mongo/protocol/delete.rb +94 -0
  132. data/lib/mongo/protocol/get_more.rb +99 -0
  133. data/lib/mongo/protocol/insert.rb +99 -0
  134. data/lib/mongo/protocol/kill_cursors.rb +74 -0
  135. data/lib/mongo/protocol/message.rb +252 -0
  136. data/lib/mongo/protocol/query.rb +147 -0
  137. data/lib/mongo/protocol/reply.rb +72 -0
  138. data/lib/mongo/protocol/serializers.rb +180 -0
  139. data/lib/mongo/protocol/update.rb +111 -0
  140. data/lib/mongo/server.rb +163 -0
  141. data/lib/mongo/server/connectable.rb +99 -0
  142. data/lib/mongo/server/connection.rb +133 -0
  143. data/lib/mongo/server/connection_pool.rb +141 -0
  144. data/lib/mongo/server/connection_pool/queue.rb +182 -0
  145. data/lib/mongo/server/context.rb +66 -0
  146. data/lib/mongo/server/description.rb +450 -0
  147. data/lib/mongo/server/description/features.rb +85 -0
  148. data/lib/mongo/server/description/inspector.rb +79 -0
  149. data/lib/mongo/server/description/inspector/primary_elected.rb +58 -0
  150. data/lib/mongo/server/description/inspector/server_added.rb +59 -0
  151. data/lib/mongo/server/description/inspector/server_removed.rb +59 -0
  152. data/lib/mongo/server/monitor.rb +160 -0
  153. data/lib/mongo/server/monitor/connection.rb +88 -0
  154. data/lib/mongo/server_selector.rb +81 -0
  155. data/lib/mongo/server_selector/nearest.rb +94 -0
  156. data/lib/mongo/server_selector/primary.rb +88 -0
  157. data/lib/mongo/server_selector/primary_preferred.rb +94 -0
  158. data/lib/mongo/server_selector/secondary.rb +91 -0
  159. data/lib/mongo/server_selector/secondary_preferred.rb +96 -0
  160. data/lib/mongo/server_selector/selectable.rb +209 -0
  161. data/lib/mongo/socket.rb +179 -0
  162. data/lib/mongo/socket/ssl.rb +108 -0
  163. data/lib/mongo/socket/tcp.rb +69 -0
  164. data/lib/mongo/socket/unix.rb +66 -0
  165. data/lib/mongo/uri.rb +504 -0
  166. data/lib/mongo/version.rb +21 -0
  167. data/lib/mongo/write_concern.rb +99 -0
  168. data/lib/mongo/write_concern/acknowledged.rb +38 -0
  169. data/lib/mongo/write_concern/normalizable.rb +73 -0
  170. data/lib/mongo/write_concern/unacknowledged.rb +43 -0
  171. data/mongo.gemspec +17 -14
  172. data/spec/mongo/address/ipv4_spec.rb +74 -0
  173. data/spec/mongo/address/ipv6_spec.rb +74 -0
  174. data/spec/mongo/address/unix_spec.rb +30 -0
  175. data/spec/mongo/address_spec.rb +206 -0
  176. data/spec/mongo/auth/cr_spec.rb +59 -0
  177. data/spec/mongo/auth/ldap_spec.rb +40 -0
  178. data/spec/mongo/auth/scram/conversation_spec.rb +197 -0
  179. data/spec/mongo/auth/scram_spec.rb +55 -0
  180. data/spec/mongo/auth/user/view_spec.rb +76 -0
  181. data/spec/mongo/auth/user_spec.rb +190 -0
  182. data/spec/mongo/auth/x509_spec.rb +40 -0
  183. data/spec/mongo/auth_spec.rb +65 -0
  184. data/spec/mongo/bulk/bulk_write_spec.rb +175 -0
  185. data/spec/mongo/client_spec.rb +564 -0
  186. data/spec/mongo/cluster/topology/replica_set_spec.rb +101 -0
  187. data/spec/mongo/cluster/topology/sharded_spec.rb +74 -0
  188. data/spec/mongo/cluster/topology/standalone_spec.rb +79 -0
  189. data/spec/mongo/cluster/topology_spec.rb +65 -0
  190. data/spec/mongo/cluster_spec.rb +129 -0
  191. data/spec/mongo/collection/view/aggregation_spec.rb +135 -0
  192. data/spec/mongo/collection/view/explainable_spec.rb +32 -0
  193. data/spec/mongo/collection/view/map_reduce_spec.rb +242 -0
  194. data/spec/mongo/collection/view/readable_spec.rb +603 -0
  195. data/spec/mongo/collection/view/writable_spec.rb +504 -0
  196. data/spec/mongo/collection/view_spec.rb +521 -0
  197. data/spec/mongo/collection_spec.rb +362 -0
  198. data/spec/mongo/cursor_spec.rb +295 -0
  199. data/spec/mongo/database_spec.rb +306 -0
  200. data/spec/mongo/error/parser_spec.rb +119 -0
  201. data/spec/mongo/event/publisher_spec.rb +50 -0
  202. data/spec/mongo/event/subscriber_spec.rb +34 -0
  203. data/spec/mongo/grid/file/chunk_spec.rb +226 -0
  204. data/spec/mongo/grid/file/metadata_spec.rb +69 -0
  205. data/spec/mongo/grid/file_spec.rb +138 -0
  206. data/spec/mongo/grid/fs_spec.rb +129 -0
  207. data/spec/mongo/index/view_spec.rb +226 -0
  208. data/spec/mongo/loggable_spec.rb +62 -0
  209. data/spec/mongo/logger_spec.rb +97 -0
  210. data/spec/mongo/operation/aggregate/result_spec.rb +80 -0
  211. data/spec/mongo/operation/aggregate_spec.rb +135 -0
  212. data/spec/mongo/operation/command_spec.rb +106 -0
  213. data/spec/mongo/operation/kill_cursors_spec.rb +66 -0
  214. data/spec/mongo/operation/limited_spec.rb +50 -0
  215. data/spec/mongo/operation/map_reduce_spec.rb +143 -0
  216. data/spec/mongo/operation/read/collections_info_spec.rb +40 -0
  217. data/spec/mongo/operation/read/get_more_spec.rb +81 -0
  218. data/spec/mongo/operation/read/indexes_spec.rb +31 -0
  219. data/spec/mongo/operation/read/query_spec.rb +84 -0
  220. data/spec/mongo/operation/result_spec.rb +275 -0
  221. data/spec/mongo/operation/specifiable_spec.rb +53 -0
  222. data/spec/mongo/operation/write/bulk_delete_spec.rb +473 -0
  223. data/spec/mongo/operation/write/bulk_insert_spec.rb +466 -0
  224. data/spec/mongo/operation/write/bulk_update_spec.rb +524 -0
  225. data/spec/mongo/operation/write/command/delete_spec.rb +116 -0
  226. data/spec/mongo/operation/write/command/insert_spec.rb +117 -0
  227. data/spec/mongo/operation/write/command/update_spec.rb +123 -0
  228. data/spec/mongo/operation/write/create_user_spec.rb +44 -0
  229. data/spec/mongo/operation/write/delete_spec.rb +178 -0
  230. data/spec/mongo/operation/write/drop_index_spec.rb +51 -0
  231. data/spec/mongo/operation/write/ensure_index_spec.rb +81 -0
  232. data/spec/mongo/operation/write/insert_spec.rb +231 -0
  233. data/spec/mongo/operation/write/remove_user_spec.rb +46 -0
  234. data/spec/mongo/operation/write/response_spec.rb +85 -0
  235. data/spec/mongo/operation/write/update_spec.rb +177 -0
  236. data/spec/mongo/protocol/delete_spec.rb +167 -0
  237. data/spec/mongo/protocol/get_more_spec.rb +146 -0
  238. data/spec/mongo/protocol/insert_spec.rb +161 -0
  239. data/spec/mongo/protocol/kill_cursors_spec.rb +101 -0
  240. data/spec/mongo/protocol/query_spec.rb +285 -0
  241. data/spec/mongo/protocol/reply_spec.rb +157 -0
  242. data/spec/mongo/protocol/update_spec.rb +186 -0
  243. data/spec/mongo/server/connection_pool/queue_spec.rb +170 -0
  244. data/spec/mongo/server/connection_pool_spec.rb +120 -0
  245. data/spec/mongo/server/connection_spec.rb +289 -0
  246. data/spec/mongo/server/description/features_spec.rb +138 -0
  247. data/spec/mongo/server/description/inspector/primary_elected_spec.rb +94 -0
  248. data/spec/mongo/server/description/inspector/server_added_spec.rb +92 -0
  249. data/spec/mongo/server/description/inspector/server_removed_spec.rb +95 -0
  250. data/spec/mongo/server/description_spec.rb +510 -0
  251. data/spec/mongo/server/monitor_spec.rb +130 -0
  252. data/spec/mongo/server_discovery_and_monitoring_spec.rb +103 -0
  253. data/spec/mongo/server_selection_rtt_spec.rb +104 -0
  254. data/spec/mongo/server_selection_spec.rb +89 -0
  255. data/spec/mongo/server_selector/nearest_spec.rb +250 -0
  256. data/spec/mongo/server_selector/primary_preferred_spec.rb +290 -0
  257. data/spec/mongo/server_selector/primary_spec.rb +114 -0
  258. data/spec/mongo/server_selector/secondary_preferred_spec.rb +252 -0
  259. data/spec/mongo/server_selector/secondary_spec.rb +196 -0
  260. data/spec/mongo/server_selector_spec.rb +101 -0
  261. data/spec/mongo/server_spec.rb +131 -0
  262. data/spec/mongo/uri_spec.rb +517 -0
  263. data/spec/mongo/write_concern/acknowledged_spec.rb +44 -0
  264. data/spec/mongo/write_concern/unacknowledged_spec.rb +15 -0
  265. data/spec/mongo_orchestration_spec.rb +70 -0
  266. data/spec/spec_helper.rb +148 -0
  267. data/spec/support/authorization.rb +245 -0
  268. data/spec/support/helpers.rb +140 -0
  269. data/spec/support/matchers.rb +37 -0
  270. data/spec/support/mongo_orchestration.rb +61 -0
  271. data/spec/support/mongo_orchestration/requestable.rb +109 -0
  272. data/spec/support/mongo_orchestration/standalone.rb +57 -0
  273. data/spec/support/sdam/rs/discover_arbiters.yml +41 -0
  274. data/spec/support/sdam/rs/discover_passives.yml +41 -0
  275. data/spec/support/sdam/rs/discover_primary.yml +40 -0
  276. data/spec/support/sdam/rs/discover_secondary.yml +41 -0
  277. data/spec/support/sdam/rs/discovery.yml +195 -0
  278. data/spec/support/sdam/rs/ghost_discovered.yml +39 -0
  279. data/spec/support/sdam/rs/hosts_differ_from_seeds.yml +34 -0
  280. data/spec/support/sdam/rs/member_reconfig.yml +68 -0
  281. data/spec/support/sdam/rs/member_standalone.yml +60 -0
  282. data/spec/support/sdam/rs/new_primary.yml +74 -0
  283. data/spec/support/sdam/rs/new_primary_wrong_set_name.yml +71 -0
  284. data/spec/support/sdam/rs/non_rs_member.yml +31 -0
  285. data/spec/support/sdam/rs/normalize_case.yml +49 -0
  286. data/spec/support/sdam/rs/primary_becomes_standalone.yml +52 -0
  287. data/spec/support/sdam/rs/primary_changes_set_name.yml +57 -0
  288. data/spec/support/sdam/rs/primary_disconnect.yml +56 -0
  289. data/spec/support/sdam/rs/primary_wrong_set_name.yml +27 -0
  290. data/spec/support/sdam/rs/response_from_removed.yml +63 -0
  291. data/spec/support/sdam/rs/rsother_discovered.yml +41 -0
  292. data/spec/support/sdam/rs/sec_not_auth.yml +49 -0
  293. data/spec/support/sdam/rs/secondary_wrong_set_name.yml +28 -0
  294. data/spec/support/sdam/rs/secondary_wrong_set_name_with_primary.yml +69 -0
  295. data/spec/support/sdam/rs/unexpected_mongos.yml +26 -0
  296. data/spec/support/sdam/rs/wrong_set_name.yml +35 -0
  297. data/spec/support/sdam/sharded/multiple_mongoses.yml +46 -0
  298. data/spec/support/sdam/sharded/non_mongos_removed.yml +41 -0
  299. data/spec/support/sdam/sharded/normalize_uri_case.yml +32 -0
  300. data/spec/support/sdam/single/direct_connection_external_ip.yml +34 -0
  301. data/spec/support/sdam/single/direct_connection_mongos.yml +33 -0
  302. data/spec/support/sdam/single/direct_connection_rsarbiter.yml +35 -0
  303. data/spec/support/sdam/single/direct_connection_rsprimary.yml +34 -0
  304. data/spec/support/sdam/single/direct_connection_rssecondary.yml +35 -0
  305. data/spec/support/sdam/single/direct_connection_slave.yml +32 -0
  306. data/spec/support/sdam/single/direct_connection_standalone.yml +32 -0
  307. data/spec/support/sdam/single/not_ok_response.yml +39 -0
  308. data/spec/support/sdam/single/standalone_removed.yml +32 -0
  309. data/spec/support/sdam/single/unavailable_seed.yml +28 -0
  310. data/spec/support/server_discovery_and_monitoring.rb +167 -0
  311. data/spec/support/server_selection.rb +140 -0
  312. data/spec/support/server_selection/rtt/first_value.yml +4 -0
  313. data/spec/support/server_selection/rtt/first_value_zero.yml +4 -0
  314. data/spec/support/server_selection/rtt/value_test_1.yml +4 -0
  315. data/spec/support/server_selection/rtt/value_test_2.yml +4 -0
  316. data/spec/support/server_selection/rtt/value_test_3.yml +4 -0
  317. data/spec/support/server_selection/rtt/value_test_4.yml +4 -0
  318. data/spec/support/server_selection/rtt/value_test_5.yml +4 -0
  319. data/spec/support/server_selection/selection/ReplicaSetNoPrimary/read/Nearest.yml +32 -0
  320. data/spec/support/server_selection/selection/ReplicaSetNoPrimary/read/Nearest_non_matching.yml +27 -0
  321. data/spec/support/server_selection/selection/ReplicaSetNoPrimary/read/Primary.yml +23 -0
  322. data/spec/support/server_selection/selection/ReplicaSetNoPrimary/read/PrimaryPreferred.yml +32 -0
  323. data/spec/support/server_selection/selection/ReplicaSetNoPrimary/read/PrimaryPreferred_non_matching.yml +27 -0
  324. data/spec/support/server_selection/selection/ReplicaSetNoPrimary/read/Secondary.yml +32 -0
  325. data/spec/support/server_selection/selection/ReplicaSetNoPrimary/read/SecondaryPreferred.yml +32 -0
  326. data/spec/support/server_selection/selection/ReplicaSetNoPrimary/read/SecondaryPreferred_non_matching.yml +27 -0
  327. data/spec/support/server_selection/selection/ReplicaSetNoPrimary/read/Secondary_non_matching.yml +27 -0
  328. data/spec/support/server_selection/selection/ReplicaSetWithPrimary/read/Nearest.yml +41 -0
  329. data/spec/support/server_selection/selection/ReplicaSetWithPrimary/read/Nearest_non_matching.yml +34 -0
  330. data/spec/support/server_selection/selection/ReplicaSetWithPrimary/read/Primary.yml +33 -0
  331. data/spec/support/server_selection/selection/ReplicaSetWithPrimary/read/PrimaryPreferred.yml +39 -0
  332. data/spec/support/server_selection/selection/ReplicaSetWithPrimary/read/PrimaryPreferred_non_matching.yml +36 -0
  333. data/spec/support/server_selection/selection/Sharded/read/SecondaryPreferred.yml +32 -0
  334. data/spec/support/server_selection/selection/Single/read/SecondaryPreferred.yml +23 -0
  335. data/spec/support/server_selection/selection/Unknown/read/SecondaryPreferred.yml +13 -0
  336. data/spec/support/server_selection_rtt.rb +41 -0
  337. data/spec/support/shared/bulk_write.rb +498 -0
  338. data/spec/support/shared/cursor.rb +38 -0
  339. data/spec/support/shared/operation.rb +77 -0
  340. data/spec/support/shared/protocol.rb +31 -0
  341. data/spec/support/shared/server_selector.rb +111 -0
  342. data/spec/support/shared/socket.rb +82 -0
  343. data/spec/support/travis.rb +14 -0
  344. metadata +523 -189
  345. metadata.gz.sig +0 -0
  346. data/VERSION +0 -1
  347. data/lib/mongo/bulk_write_collection_view.rb +0 -387
  348. data/lib/mongo/collection_writer.rb +0 -364
  349. data/lib/mongo/connection/node.rb +0 -249
  350. data/lib/mongo/connection/pool.rb +0 -340
  351. data/lib/mongo/connection/pool_manager.rb +0 -320
  352. data/lib/mongo/connection/sharding_pool_manager.rb +0 -67
  353. data/lib/mongo/connection/socket/ssl_socket.rb +0 -95
  354. data/lib/mongo/connection/socket/tcp_socket.rb +0 -87
  355. data/lib/mongo/connection/socket/unix_socket.rb +0 -39
  356. data/lib/mongo/db.rb +0 -808
  357. data/lib/mongo/exception.rb +0 -145
  358. data/lib/mongo/functional/authentication.rb +0 -455
  359. data/lib/mongo/functional/logging.rb +0 -85
  360. data/lib/mongo/functional/read_preference.rb +0 -183
  361. data/lib/mongo/functional/scram.rb +0 -556
  362. data/lib/mongo/functional/uri_parser.rb +0 -409
  363. data/lib/mongo/functional/write_concern.rb +0 -66
  364. data/lib/mongo/gridfs/grid.rb +0 -112
  365. data/lib/mongo/gridfs/grid_ext.rb +0 -53
  366. data/lib/mongo/gridfs/grid_file_system.rb +0 -163
  367. data/lib/mongo/gridfs/grid_io.rb +0 -484
  368. data/lib/mongo/legacy.rb +0 -140
  369. data/lib/mongo/mongo_client.rb +0 -697
  370. data/lib/mongo/mongo_replica_set_client.rb +0 -535
  371. data/lib/mongo/mongo_sharded_client.rb +0 -159
  372. data/lib/mongo/networking.rb +0 -372
  373. data/lib/mongo/utils/conversions.rb +0 -110
  374. data/lib/mongo/utils/core_ext.rb +0 -70
  375. data/lib/mongo/utils/server_version.rb +0 -69
  376. data/lib/mongo/utils/support.rb +0 -80
  377. data/test/functional/authentication_test.rb +0 -39
  378. data/test/functional/bulk_api_stress_test.rb +0 -133
  379. data/test/functional/bulk_write_collection_view_test.rb +0 -1198
  380. data/test/functional/client_test.rb +0 -627
  381. data/test/functional/collection_test.rb +0 -2175
  382. data/test/functional/collection_writer_test.rb +0 -83
  383. data/test/functional/conversions_test.rb +0 -163
  384. data/test/functional/cursor_fail_test.rb +0 -57
  385. data/test/functional/cursor_message_test.rb +0 -56
  386. data/test/functional/cursor_test.rb +0 -683
  387. data/test/functional/db_api_test.rb +0 -835
  388. data/test/functional/db_test.rb +0 -348
  389. data/test/functional/grid_file_system_test.rb +0 -285
  390. data/test/functional/grid_io_test.rb +0 -252
  391. data/test/functional/grid_test.rb +0 -273
  392. data/test/functional/pool_test.rb +0 -136
  393. data/test/functional/safe_test.rb +0 -98
  394. data/test/functional/support_test.rb +0 -62
  395. data/test/functional/timeout_test.rb +0 -60
  396. data/test/functional/uri_test.rb +0 -446
  397. data/test/functional/write_concern_test.rb +0 -118
  398. data/test/helpers/general.rb +0 -50
  399. data/test/helpers/test_unit.rb +0 -476
  400. data/test/replica_set/authentication_test.rb +0 -37
  401. data/test/replica_set/basic_test.rb +0 -189
  402. data/test/replica_set/client_test.rb +0 -393
  403. data/test/replica_set/connection_test.rb +0 -138
  404. data/test/replica_set/count_test.rb +0 -66
  405. data/test/replica_set/cursor_test.rb +0 -220
  406. data/test/replica_set/insert_test.rb +0 -157
  407. data/test/replica_set/max_values_test.rb +0 -151
  408. data/test/replica_set/pinning_test.rb +0 -105
  409. data/test/replica_set/query_test.rb +0 -73
  410. data/test/replica_set/read_preference_test.rb +0 -219
  411. data/test/replica_set/refresh_test.rb +0 -211
  412. data/test/replica_set/replication_ack_test.rb +0 -95
  413. data/test/sharded_cluster/basic_test.rb +0 -203
  414. data/test/shared/authentication/basic_auth_shared.rb +0 -260
  415. data/test/shared/authentication/bulk_api_auth_shared.rb +0 -249
  416. data/test/shared/authentication/gssapi_shared.rb +0 -176
  417. data/test/shared/authentication/sasl_plain_shared.rb +0 -96
  418. data/test/shared/authentication/scram_shared.rb +0 -92
  419. data/test/shared/ssl_shared.rb +0 -235
  420. data/test/test_helper.rb +0 -61
  421. data/test/threading/basic_test.rb +0 -120
  422. data/test/tools/mongo_config.rb +0 -708
  423. data/test/tools/mongo_config_test.rb +0 -160
  424. data/test/unit/client_test.rb +0 -381
  425. data/test/unit/collection_test.rb +0 -166
  426. data/test/unit/connection_test.rb +0 -335
  427. data/test/unit/cursor_test.rb +0 -307
  428. data/test/unit/db_test.rb +0 -136
  429. data/test/unit/grid_test.rb +0 -76
  430. data/test/unit/mongo_sharded_client_test.rb +0 -48
  431. data/test/unit/node_test.rb +0 -93
  432. data/test/unit/pool_manager_test.rb +0 -111
  433. data/test/unit/read_pref_test.rb +0 -406
  434. data/test/unit/read_test.rb +0 -159
  435. data/test/unit/safe_test.rb +0 -158
  436. data/test/unit/sharding_pool_manager_test.rb +0 -84
  437. data/test/unit/write_concern_test.rb +0 -175
metadata.gz.sig CHANGED
Binary file
data/VERSION DELETED
@@ -1 +0,0 @@
1
- 1.12.5
@@ -1,387 +0,0 @@
1
- # Copyright (C) 2009-2013 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
-
17
- # A bulk write view to a collection of documents in a database.
18
- class BulkWriteCollectionView
19
- include Mongo::WriteConcern
20
-
21
- DEFAULT_OP_ARGS = {:q => nil}
22
- MULTIPLE_ERRORS_MSG = "batch item errors occurred"
23
- EMPTY_BATCH_MSG = "batch is empty"
24
-
25
- attr_reader :collection, :options, :ops, :op_args
26
-
27
- # Initialize a bulk-write-view object to a collection with default query selector {}.
28
- #
29
- # A bulk write operation is initialized from a collection object.
30
- # For example, for an ordered bulk write view:
31
- #
32
- # bulk = collection.initialize_ordered_bulk_op
33
- #
34
- # or for an unordered bulk write view:
35
- #
36
- # bulk = collection.initialize_unordered_bulk_op
37
- #
38
- # The bulk write view collects individual write operations together so that they can be
39
- # executed as a batch for significant performance gains.
40
- # The ordered bulk operation will execute each operation serially in order.
41
- # Execution will stop at the first occurrence of an error for an ordered bulk operation.
42
- # The unordered bulk operation will be executed and may take advantage of parallelism.
43
- # There are no guarantees for the order of execution of the operations on the server.
44
- # Execution will continue even if there are errors for an unordered bulk operation.
45
- #
46
- # A bulk operation is programmed as a sequence of individual operations.
47
- # An individual operation is composed of a method chain of modifiers or setters terminated by a write method.
48
- # A modify method sets a value on the current object.
49
- # A set methods returns a duplicate of the current object with a value set.
50
- # A terminator write method appends a write operation to the bulk batch collected in the view.
51
- #
52
- # The API supports mixing of write operation types in a bulk operation.
53
- # However, server support affects the implementation and performance of bulk operations.
54
- #
55
- # MongoDB version 2.6 servers currently support only bulk commands of the same type.
56
- # With an ordered bulk operation,
57
- # contiguous individual ops of the same type can be batched into the same db request,
58
- # and the next op of a different type must be sent separately in the next request.
59
- # Performance will improve if you can arrange your ops to reduce the number of db requests.
60
- # With an unordered bulk operation,
61
- # individual ops can be grouped by type and sent in at most three requests,
62
- # one each per insert, update, or delete.
63
- #
64
- # MongoDB pre-version 2.6 servers do not support bulk write commands.
65
- # The bulk operation must be sent one request per individual op.
66
- # This also applies to inserts in order to have accurate counts and error reporting.
67
- #
68
- # Important note on pre-2.6 performance:
69
- # Performance is very poor compared to version 2.6.
70
- # We recommend bulk operation with pre-2.6 only for compatibility or
71
- # for development in preparation for version 2.6.
72
- # For better performance with pre-version 2.6, use bulk insertion with Collection#insert.
73
- #
74
- # @param [Collection] collection the parent collection object
75
- #
76
- # @option opts [Boolean] :ordered (true) Set bulk execution for ordered or unordered
77
- #
78
- # @return [BulkWriteCollectionView]
79
- def initialize(collection, options = {})
80
- @collection = collection
81
- @options = options
82
- @ops = []
83
- @op_args = DEFAULT_OP_ARGS.dup
84
- end
85
-
86
- def inspect
87
- vars = [:@options, :@ops, :@op_args]
88
- vars_inspect = vars.collect{|var| "#{var}=#{instance_variable_get(var).inspect}"}
89
- "#<Mongo::BulkWriteCollectionView:0x#{self.object_id} " <<
90
- "@collection=#<Mongo::Collection:0x#{@collection.object_id}>, #{vars_inspect.join(', ')}>"
91
- end
92
-
93
- # Modify the query selector for subsequent bulk write operations.
94
- # The default query selector on creation of the bulk write view is {}.
95
- # For operations that require a query selector, find() must be set
96
- # per operation, or set once for all operations on the bulk object.
97
- # For example, these operations:
98
- #
99
- # bulk.find({"a" => 2}).update({"$inc" => {"x" => 2}})
100
- # bulk.find({"a" => 2}).update({"$set" => {"b" => 3}})
101
- #
102
- # may be rewritten as:
103
- #
104
- # bulk = find({"a" => 2})
105
- # bulk.update({"$inc" => {"x" => 2}})
106
- # bulk.update({"$set" => {"b" => 3}})
107
- #
108
- # Note that modifying the query selector in this way will not affect
109
- # operations that do not use a query selector, like insert().
110
- #
111
- # @param [Hash] q the query selector
112
- #
113
- # @return [BulkWriteCollectionView]
114
- def find(q)
115
- op_args_set(:q, q)
116
- end
117
-
118
- # Modify the upsert option argument for subsequent bulk write operations.
119
- #
120
- # @param [Boolean] value (true) the upsert option value
121
- #
122
- # @return [BulkWriteCollectionView]
123
- def upsert!(value = true)
124
- op_args_set(:upsert, value)
125
- end
126
-
127
- # Set the upsert option argument for subsequent bulk write operations.
128
- #
129
- # @param [Boolean] value (true) the upsert option value
130
- #
131
- # @return [BulkWriteCollectionView] a duplicated object
132
- def upsert(value = true)
133
- dup.upsert!(value)
134
- end
135
-
136
- # Update one document matching the selector.
137
- #
138
- # bulk.find({"a" => 1}).update_one({"$inc" => {"x" => 1}})
139
- #
140
- # Use the upsert! or upsert method to specify an upsert. For example:
141
- #
142
- # bulk.find({"a" => 1}).upsert.updateOne({"$inc" => {"x" => 1}})
143
- #
144
- # @param [Hash] u the update document
145
- #
146
- # @return [BulkWriteCollectionView]
147
- def update_one(u)
148
- raise MongoArgumentError, "document must start with an operator" unless update_doc?(u)
149
- op_push([:update, @op_args.merge(:u => u, :multi => false)])
150
- end
151
-
152
- # Update all documents matching the selector. For example:
153
- #
154
- # bulk.find({"a" => 2}).update({"$inc" => {"x" => 2}})
155
- #
156
- # Use the upsert! or upsert method to specify an upsert. For example:
157
- #
158
- # bulk.find({"a" => 2}).upsert.update({"$inc" => {"x" => 2}})
159
- #
160
- # @param [Hash] u the update document
161
- #
162
- # @return [BulkWriteCollectionView]
163
- def update(u)
164
- raise MongoArgumentError, "document must start with an operator" unless update_doc?(u)
165
- op_push([:update, @op_args.merge(:u => u, :multi => true)])
166
- end
167
-
168
- # Replace entire document (update with whole doc replace). For example:
169
- #
170
- # bulk.find({"a" => 3}).replace_one({"x" => 3})
171
- #
172
- # @param [Hash] u the replacement document
173
- #
174
- # @return [BulkWriteCollectionView]
175
- def replace_one(u)
176
- raise MongoArgumentError, "document must not contain any operators" unless replace_doc?(u)
177
- op_push([:update, @op_args.merge(:u => u, :multi => false)])
178
- end
179
-
180
- # Remove a single document matching the selector. For example:
181
- #
182
- # bulk.find({"a" => 4}).remove_one;
183
- #
184
- # @return [BulkWriteCollectionView]
185
- def remove_one
186
- op_push([:delete, @op_args.merge(:limit => 1)])
187
- end
188
-
189
- # Remove all documents matching the selector. For example:
190
- #
191
- # bulk.find({"a" => 5}).remove;
192
- #
193
- # @return [BulkWriteCollectionView]
194
- def remove
195
- op_push([:delete, @op_args.merge(:limit => 0)])
196
- end
197
-
198
- # Insert a document. For example:
199
- #
200
- # bulk.insert({"x" => 4})
201
- #
202
- # @return [BulkWriteCollectionView]
203
- def insert(document)
204
- # TODO - check keys
205
- op_push([:insert, {:d => document}])
206
- end
207
-
208
- # Execute the bulk operation, with an optional write concern overwriting the default w:1.
209
- # For example:
210
- #
211
- # write_concern = {:w => 1, :j => 1}
212
- # bulk.execute({write_concern})
213
- #
214
- # On return from execute, the bulk operation is cleared,
215
- # but the selector and upsert settings are preserved.
216
- #
217
- # @return [BulkWriteCollectionView]
218
- def execute(opts = {})
219
- raise MongoArgumentError, EMPTY_BATCH_MSG if @ops.empty?
220
- write_concern = get_write_concern(opts, @collection)
221
- @ops.each_with_index{|op, index| op.last.merge!(:ord => index)} # infuse ordinal here to avoid issues with upsert
222
- if @collection.db.connection.use_write_command?(write_concern)
223
- errors, write_concern_errors, exchanges = @collection.command_writer.bulk_execute(@ops, @options, opts)
224
- else
225
- errors, write_concern_errors, exchanges = @collection.operation_writer.bulk_execute(@ops, @options, opts)
226
- end
227
- @ops = []
228
- return true if errors.empty? && (exchanges.empty? || exchanges.first[:response] == true) # w 0 without GLE
229
- result = merge_result(errors + write_concern_errors, exchanges)
230
- raise BulkWriteError.new(MULTIPLE_ERRORS_MSG, Mongo::ErrorCode::MULTIPLE_ERRORS_OCCURRED, result) if !errors.empty? || !write_concern_errors.empty?
231
- result
232
- end
233
-
234
- private
235
-
236
- def hash_except(h, *keys)
237
- keys.each { |key| h.delete(key) }
238
- h
239
- end
240
-
241
- def hash_select(h, *keys)
242
- Hash[*keys.zip(h.values_at(*keys)).flatten]
243
- end
244
-
245
- def tally(h, key, n)
246
- h[key] = h.fetch(key, 0) + n
247
- end
248
-
249
- def nil_tally(h, key, n)
250
- if !h.has_key?(key)
251
- h[key] = n
252
- elsif h[key]
253
- h[key] = n ? h[key] + n : n
254
- end
255
- end
256
-
257
- def append(h, key, obj)
258
- h[key] = h.fetch(key, []) << obj
259
- end
260
-
261
- def concat(h, key, a)
262
- h[key] = h.fetch(key, []) + a
263
- end
264
-
265
- def merge_index(h, exchange)
266
- h.merge("index" => exchange[:batch][h.fetch("index", 0)][:ord])
267
- end
268
-
269
- def merge_indexes(a, exchange)
270
- a.collect{|h| merge_index(h, exchange)}
271
- end
272
-
273
- def merge_result(errors, exchanges)
274
- ok = 0
275
- result = {"ok" => 0, "n" => 0}
276
- unless errors.empty?
277
- unless (writeErrors = errors.select { |error| error.class != Mongo::OperationFailure && error.class != WriteConcernError }).empty? # assignment
278
- concat(result, "writeErrors",
279
- writeErrors.collect { |error|
280
- {"index" => error.result[:ord], "code" => error.error_code, "errmsg" => error.result[:error].message}
281
- })
282
- end
283
- result.merge!("code" => Mongo::ErrorCode::MULTIPLE_ERRORS_OCCURRED, "errmsg" => MULTIPLE_ERRORS_MSG)
284
- end
285
- exchanges.each do |exchange|
286
- response = exchange[:response]
287
- next unless response
288
- ok += response["ok"].to_i
289
- n = response["n"] || 0
290
- op_type = exchange[:op_type]
291
- if op_type == :insert
292
- n = 1 if response.key?("err") && (response["err"].nil? || response["err"] == "norepl" || response["err"] == "timeout") # OP_INSERT override n = 0 bug, n = exchange[:batch].size always 1
293
- tally(result, "nInserted", n)
294
- elsif op_type == :update
295
- n_upserted = 0
296
- if (upserted = response.fetch("upserted", nil)) # assignment
297
- upserted = [{"_id" => upserted}] if upserted.class != Array # OP_UPDATE non-array
298
- n_upserted = upserted.size
299
- concat(result, "upserted", merge_indexes(upserted, exchange))
300
- elsif (response["updatedExisting"] == false && n == 1)
301
- # workaround for DRIVERS-151 (non-ObjectID _id fields in pre-2.6 servers)
302
- op = exchange[:batch][0]
303
- missing_id = op[:u].fetch(:_id, op[:q][:_id]) # _id in update document takes precedence
304
- upserted = [ { "_id" => missing_id, "index" => 0 } ]
305
- n_upserted = n
306
- concat(result, "upserted", merge_indexes(upserted, exchange))
307
- end
308
- tally(result, "nUpserted", n_upserted) if n_upserted > 0
309
- tally(result, "nMatched", n - n_upserted)
310
- nil_tally(result, "nModified", response["nModified"])
311
- elsif op_type == :delete
312
- tally(result, "nRemoved", n)
313
- end
314
- result["n"] += n
315
- write_concern_error = nil
316
- errmsg = response["errmsg"] || response["err"] # top level
317
- if (writeErrors = response["writeErrors"] || response["errDetails"]) # assignment
318
- concat(result, "writeErrors", merge_indexes(writeErrors, exchange))
319
- elsif response["err"] == "timeout" # errmsg == "timed out waiting for slaves" # OP_*
320
- write_concern_error = {"errmsg" => errmsg, "code" => Mongo::ErrorCode::WRITE_CONCERN_FAILED,
321
- "errInfo" => {"wtimeout" => response["wtimeout"]}} # OP_* does not have "code"
322
- elsif errmsg == "norepl" # OP_*
323
- write_concern_error = {"errmsg" => errmsg, "code" => Mongo::ErrorCode::WRITE_CONCERN_FAILED} # OP_* does not have "code"
324
- elsif errmsg # OP_INSERT, OP_UPDATE have "err"
325
- append(result, "writeErrors", merge_index({"errmsg" => errmsg, "code" => response["code"]}, exchange))
326
- end
327
- if response["writeConcernError"]
328
- write_concern_error = response["writeConcernError"]
329
- elsif (wnote = response["wnote"]) # assignment - OP_*
330
- write_concern_error = {"errmsg" => wnote, "code" => Mongo::ErrorCode::WRITE_CONCERN_FAILED} # OP_* does not have "code"
331
- elsif (jnote = response["jnote"]) # assignment - OP_*
332
- write_concern_error = {"errmsg" => jnote, "code" => Mongo::ErrorCode::BAD_VALUE} # OP_* does not have "code"
333
- end
334
- append(result, "writeConcernError", merge_index(write_concern_error, exchange)) if write_concern_error
335
- end
336
- result.delete("nModified") if result.has_key?("nModified") && !result["nModified"]
337
- result.merge!("ok" => [ok + result["n"], 1].min)
338
- end
339
-
340
- def initialize_copy(other)
341
- other.instance_variable_set(:@options, other.options.dup)
342
- end
343
-
344
- def op_args_set(op, value)
345
- @op_args[op] = value
346
- self
347
- end
348
-
349
- def op_push(op)
350
- raise MongoArgumentError, "non-nil query must be set via find" if op.first != :insert && !op.last[:q]
351
- @ops << op
352
- self
353
- end
354
-
355
- def update_doc?(doc)
356
- !doc.empty? && doc.keys.first.to_s =~ /^\$/
357
- end
358
-
359
- def replace_doc?(doc)
360
- doc.keys.all?{|key| key !~ /^\$/}
361
- end
362
-
363
- end
364
-
365
- class Collection
366
-
367
- # Initialize an ordered bulk write view for this collection
368
- # Execution will stop at the first occurrence of an error for an ordered bulk operation.
369
- #
370
- # @return [BulkWriteCollectionView]
371
- def initialize_ordered_bulk_op
372
- BulkWriteCollectionView.new(self, :ordered => true)
373
- end
374
-
375
- # Initialize an unordered bulk write view for this collection
376
- # The unordered bulk operation will be executed and may take advantage of parallelism.
377
- # There are no guarantees for the order of execution of the operations on the server.
378
- # Execution will continue even if there are errors for an unordered bulk operation.
379
- #
380
- # @return [BulkWriteCollectionView]
381
- def initialize_unordered_bulk_op
382
- BulkWriteCollectionView.new(self, :ordered => false)
383
- end
384
-
385
- end
386
-
387
- end
@@ -1,364 +0,0 @@
1
- # Copyright (C) 2009-2013 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
-
17
- class CollectionWriter
18
- include Mongo::Logging
19
- include Mongo::WriteConcern
20
-
21
- OPCODE = {
22
- :insert => Mongo::Constants::OP_INSERT,
23
- :update => Mongo::Constants::OP_UPDATE,
24
- :delete => Mongo::Constants::OP_DELETE
25
- }
26
- WRITE_COMMAND_ARG_KEY = {
27
- :insert => :documents,
28
- :update => :updates,
29
- :delete => :deletes
30
- }
31
-
32
- def initialize(collection)
33
- @collection = collection
34
- @name = @collection.name
35
- @db = @collection.db
36
- @connection = @db.connection
37
- @logger = @connection.logger
38
- @max_write_batch_size = Mongo::MongoClient::DEFAULT_MAX_WRITE_BATCH_SIZE
39
- end
40
-
41
- # common implementation only for new batch write commands (insert, update, delete) and old batch insert
42
- def batch_write_incremental(op_type, documents, check_keys=true, opts={})
43
- raise Mongo::OperationFailure, "Request contains no documents" if documents.empty?
44
- write_concern = get_write_concern(opts, @collection)
45
- max_message_size, max_append_size, max_serialize_size = batch_write_max_sizes(write_concern)
46
- ordered = opts[:ordered]
47
- continue_on_error = !!opts[:continue_on_error] || ordered == false
48
- collect_on_error = !!opts[:collect_on_error] || ordered == false
49
- error_docs = [] # docs with serialization errors
50
- errors = []
51
- write_concern_errors = []
52
- exchanges = []
53
- serialized_doc = nil
54
- message = BSON::ByteBuffer.new("", max_message_size)
55
- @max_write_batch_size = @collection.db.connection.max_write_batch_size
56
- docs = documents.dup
57
- catch(:error) do
58
- until docs.empty? || (!errors.empty? && !collect_on_error && !continue_on_error) # process documents a batch at a time
59
- batch_docs = []
60
- batch_message_initialize(message, op_type, continue_on_error, write_concern)
61
- while !docs.empty? && batch_docs.size < @max_write_batch_size
62
- begin
63
- doc = docs.first
64
- doc = doc[:d] if op_type == :insert && !ordered.nil? #check_keys for :update outside of serialize
65
- serialized_doc ||= BSON::BSON_CODER.serialize(doc, check_keys, true, max_serialize_size)
66
- rescue BSON::InvalidDocument, BSON::InvalidKeyName, BSON::InvalidStringEncoding => ex
67
- bulk_message = "Bulk write error - #{ex.message} - examine result for complete information"
68
- ex = BulkWriteError.new(bulk_message, Mongo::ErrorCode::INVALID_BSON,
69
- {:op_type => op_type, :serialize => doc, :ord => docs.first[:ord], :error => ex}) unless ordered.nil?
70
- error_docs << docs.shift
71
- errors << ex
72
- next if collect_on_error
73
- throw(:error) if batch_docs.empty?
74
- break # defer exit and send batch
75
- end
76
- break if message.size + serialized_doc.size > max_append_size
77
- batch_docs << docs.shift
78
- batch_message_append(message, serialized_doc, write_concern)
79
- serialized_doc = nil
80
- end
81
- begin
82
- response = batch_message_send(message, op_type, batch_docs, write_concern, continue_on_error) if batch_docs.size > 0
83
- exchanges << {:op_type => op_type, :batch => batch_docs, :opts => opts, :response => response}
84
- rescue Mongo::WriteConcernError => ex
85
- write_concern_errors << ex
86
- exchanges << {:op_type => op_type, :batch => batch_docs, :opts => opts, :response => ex.result}
87
- rescue Mongo::OperationFailure => ex
88
- errors << ex
89
- exchanges << {:op_type => op_type, :batch => batch_docs, :opts => opts, :response => ex.result}
90
- throw(:error) unless continue_on_error
91
- end
92
- end
93
- end
94
- [error_docs, errors, write_concern_errors, exchanges]
95
- end
96
-
97
- def batch_write_partition(op_type, documents, check_keys, opts)
98
- raise Mongo::OperationFailure, "Request contains no documents" if documents.empty?
99
- write_concern = get_write_concern(opts, @collection)
100
- ordered = opts[:ordered]
101
- continue_on_error = !!opts[:continue_on_error] || ordered == false # continue_on_error default false
102
- collect_on_error = !!opts[:collect_on_error] # collect_on_error default false
103
- error_docs = [] # docs with serialization errors
104
- errors = []
105
- write_concern_errors = []
106
- exchanges = []
107
- @max_write_batch_size = @collection.db.connection.max_write_batch_size
108
- @write_batch_size = [documents.size, @max_write_batch_size].min
109
- docs = documents.dup
110
- until docs.empty?
111
- batch = docs.take(@write_batch_size)
112
- begin
113
- batch_to_send = batch #(op_type == :insert && !ordered.nil?) ? batch.collect{|doc|doc[:d]} : batch
114
- if @collection.db.connection.use_write_command?(write_concern) # TODO - polymorphic send_write including legacy insert
115
- response = send_bulk_write_command(op_type, batch_to_send, check_keys, opts)
116
- else
117
- response = send_write_operation(op_type, nil, batch_to_send, check_keys, opts, write_concern)
118
- end
119
- exchanges << {:op_type => op_type, :batch => batch, :opts => opts, :response => response}
120
- docs = docs.drop(batch.size)
121
- @write_batch_size = [(@write_batch_size*1097) >> 10, @write_batch_size+1].max unless docs.empty? # 2**(1/10) multiplicative increase
122
- @write_batch_size = @max_write_batch_size if @write_batch_size > @max_write_batch_size
123
- rescue BSON::InvalidDocument, BSON::InvalidKeyName, BSON::InvalidStringEncoding => ex
124
- if @write_batch_size > 1 # decrease batch size
125
- @write_batch_size = (@write_batch_size+1) >> 1 # 2**(-1) multiplicative decrease
126
- next
127
- end
128
- # error on a single document
129
- bulk_message = "Bulk write error - #{ex.message} - examine result for complete information"
130
- ex = BulkWriteError.new(bulk_message, Mongo::ErrorCode::INVALID_BSON,
131
- {:op_type => op_type, :batch => batch, :ord => batch.first[:ord], :opts => opts, :error => ex}) unless ordered.nil?
132
- error_docs << docs.shift
133
- next if collect_on_error
134
- errors << ex
135
- break unless continue_on_error
136
- rescue Mongo::WriteConcernError => ex
137
- write_concern_errors << ex
138
- exchanges << {:op_type => op_type, :batch => batch_docs, :opts => opts, :response => ex.result}
139
- docs = docs.drop(batch.size)
140
- rescue Mongo::OperationFailure => ex
141
- errors << ex
142
- exchanges << {:op_type => op_type, :batch => batch, :opts => opts, :response => ex.result}
143
- docs = docs.drop(batch.size)
144
- break if !continue_on_error && !collect_on_error
145
- end
146
- end
147
- [error_docs, errors, write_concern_errors, exchanges]
148
- end
149
-
150
- alias :batch_write :batch_write_incremental
151
-
152
- def send_bulk_write_command(op_type, documents, check_keys, opts, collection_name=@name)
153
- if op_type == :insert
154
- documents = documents.collect{|doc| doc[:d]} if opts.key?(:ordered)
155
- documents.each do |doc|
156
- # TODO - @pk_factory.create_pk(doc)
157
- if check_keys
158
- doc.each_key do |key|
159
- key = key.to_s
160
- raise BSON::InvalidKeyName.new("key #{key} must not start with '$'") if key[0] == ?$
161
- raise BSON::InvalidKeyName.new("key #{key} must not contain '.'") if key.include? ?.
162
- end
163
- end
164
- end
165
- #elsif op_type == :update # TODO - check keys
166
- #elsif op_type == :delete
167
- #else
168
- # raise ArgumentError, "Write operation type must be :insert, :update or :delete"
169
- end
170
- request = BSON::OrderedHash[op_type, collection_name].merge!(
171
- Mongo::CollectionWriter::WRITE_COMMAND_ARG_KEY[op_type] => documents,
172
- :writeConcern => get_write_concern(opts, @collection),
173
- :ordered => opts[:ordered] || !opts[:continue_on_error]
174
- )
175
- @db.command(request)
176
- end
177
-
178
- private
179
-
180
- def sort_by_first_sym(pairs)
181
- pairs = pairs.collect{|first, rest| [first.to_s, rest]} #stringify_first
182
- pairs = pairs.sort{|x,y| x.first <=> y.first }
183
- pairs.collect{|first, rest| [first.to_sym, rest]} #symbolize_first
184
- end
185
-
186
- def ordered_group_by_first(pairs)
187
- pairs.inject([[], nil]) do |memo, pair|
188
- result, previous_value = memo
189
- current_value = pair.first
190
- result << [current_value, []] if previous_value != current_value
191
- result.last.last << pair.last
192
- [result, current_value]
193
- end.first
194
- end
195
-
196
- end
197
-
198
- class CollectionOperationWriter < CollectionWriter
199
- def initialize(collection)
200
- super(collection)
201
- end
202
-
203
- def send_write_operation(op_type, selector, doc_or_docs, check_keys, opts, write_concern, collection_name=@name)
204
- message = BSON::ByteBuffer.new("", @connection.max_message_size)
205
- message.put_int((op_type == :insert && !!opts[:continue_on_error]) ? 1 : 0)
206
- BSON::BSON_RUBY.serialize_cstr(message, "#{@db.name}.#{collection_name}")
207
- if op_type == :update
208
- update_options = 0
209
- update_options += 1 if opts[:upsert]
210
- update_options += 2 if opts[:multi]
211
- message.put_int(update_options)
212
- elsif op_type == :delete
213
- delete_options = 0
214
- delete_options += 1 if opts[:limit] && opts[:limit] != 0
215
- message.put_int(delete_options)
216
- end
217
- message.put_binary(BSON::BSON_CODER.serialize(selector, false, true, @connection.max_bson_size).to_s) if selector
218
- [doc_or_docs].flatten(1).compact.each do |document|
219
- message.put_binary(BSON::BSON_CODER.serialize(document, check_keys, true, @connection.max_bson_size).to_s)
220
- if message.size > @connection.max_message_size
221
- raise BSON::InvalidDocument, "Message is too large. This message is limited to #{@connection.max_message_size} bytes."
222
- end
223
- end
224
- instrument(op_type, :database => @db.name, :collection => collection_name, :selector => selector, :documents => doc_or_docs) do
225
- op_code = OPCODE[op_type]
226
- if Mongo::WriteConcern.gle?(write_concern)
227
- @connection.send_message_with_gle(op_code, message, @db.name, nil, write_concern)
228
- else
229
- @connection.send_message(op_code, message)
230
- end
231
- end
232
- end
233
-
234
- def bulk_execute(ops, options, opts = {})
235
- write_concern = get_write_concern(opts, @collection)
236
- errors = []
237
- write_concern_errors = []
238
- exchanges = []
239
- ops.each do |op_type, doc|
240
- doc = {:d => @collection.pk_factory.create_pk(doc[:d]), :ord => doc[:ord]} if op_type == :insert
241
- doc_opts = doc.merge(opts)
242
- d = doc_opts.delete(:d)
243
- q = doc_opts.delete(:q)
244
- u = doc_opts.delete(:u)
245
- begin # use single and NOT batch inserts since there no index for an error
246
- response = @collection.operation_writer.send_write_operation(op_type, q, d || u, check_keys = false, doc_opts, write_concern)
247
- exchanges << {:op_type => op_type, :batch => [doc], :opts => opts, :response => response}
248
- rescue BSON::InvalidDocument, BSON::InvalidKeyName, BSON::InvalidStringEncoding => ex
249
- bulk_message = "Bulk write error - #{ex.message} - examine result for complete information"
250
- ex = BulkWriteError.new(bulk_message, Mongo::ErrorCode::INVALID_BSON,
251
- {:op_type => op_type, :serialize => doc, :ord => doc[:ord], :error => ex})
252
- errors << ex
253
- break if options[:ordered]
254
- rescue Mongo::WriteConcernError => ex
255
- write_concern_errors << ex
256
- exchanges << {:op_type => op_type, :batch => [doc], :opts => opts, :response => ex.result}
257
- rescue Mongo::OperationFailure => ex
258
- errors << ex
259
- exchanges << {:op_type => op_type, :batch => [doc], :opts => opts, :response => ex.result}
260
- break if options[:ordered] && ex.result["err"] != "norepl"
261
- end
262
- end
263
- [errors, write_concern_errors, exchanges]
264
- end
265
-
266
- private
267
-
268
- def batch_message_initialize(message, op_type, continue_on_error, write_concern)
269
- message.clear!.clear
270
- message.put_int(continue_on_error ? 1 : 0)
271
- BSON::BSON_RUBY.serialize_cstr(message, "#{@db.name}.#{@name}")
272
- end
273
-
274
- def batch_message_append(message, serialized_doc, write_concern)
275
- message.put_binary(serialized_doc.to_s)
276
- end
277
-
278
- def batch_message_send(message, op_type, batch_docs, write_concern, continue_on_error)
279
- instrument(:insert, :database => @db.name, :collection => @name, :documents => batch_docs) do
280
- if Mongo::WriteConcern.gle?(write_concern)
281
- @connection.send_message_with_gle(Mongo::Constants::OP_INSERT, message, @db.name, nil, write_concern)
282
- else
283
- @connection.send_message(Mongo::Constants::OP_INSERT, message)
284
- end
285
- end
286
- end
287
-
288
- def batch_write_max_sizes(write_concern)
289
- [@connection.max_message_size, @connection.max_message_size, @connection.max_bson_size]
290
- end
291
-
292
- end
293
-
294
- class CollectionCommandWriter < CollectionWriter
295
- def initialize(collection)
296
- super(collection)
297
- end
298
-
299
- def send_write_command(op_type, selector, doc_or_docs, check_keys, opts, write_concern, collection_name=@name)
300
- if op_type == :insert
301
- argument = [doc_or_docs].flatten(1).compact
302
- elsif op_type == :update
303
- argument = [{:q => selector, :u => doc_or_docs, :multi => !!opts[:multi]}]
304
- argument.first.merge!(:upsert => opts[:upsert]) if opts[:upsert]
305
- elsif op_type == :delete
306
- argument = [{:q => selector, :limit => (opts[:limit] || 0)}]
307
- else
308
- raise ArgumentError, "Write operation type must be :insert, :update or :delete"
309
- end
310
- request = BSON::OrderedHash[op_type, collection_name, WRITE_COMMAND_ARG_KEY[op_type], argument]
311
- request.merge!(:writeConcern => write_concern, :ordered => !opts[:continue_on_error])
312
- request.merge!(opts)
313
- instrument(op_type, :database => @db.name, :collection => collection_name, :selector => selector, :documents => doc_or_docs) do
314
- @db.command(request)
315
- end
316
- end
317
-
318
- def bulk_execute(ops, options, opts = {})
319
- errors = []
320
- write_concern_errors = []
321
- exchanges = []
322
- ops = (options[:ordered] == false) ? sort_by_first_sym(ops) : ops # sort by write-type
323
- ordered_group_by_first(ops).each do |op_type, documents|
324
- documents.collect! {|doc| {:d => @collection.pk_factory.create_pk(doc[:d]), :ord => doc[:ord]} } if op_type == :insert
325
- error_docs, batch_errors, batch_write_concern_errors, batch_exchanges =
326
- batch_write(op_type, documents, check_keys = false, opts.merge(:ordered => options[:ordered]))
327
- errors += batch_errors
328
- write_concern_errors += batch_write_concern_errors
329
- exchanges += batch_exchanges
330
- break if options[:ordered] && !batch_errors.empty?
331
- end
332
- [errors, write_concern_errors, exchanges]
333
- end
334
-
335
- private
336
-
337
- def batch_message_initialize(message, op_type, continue_on_error, write_concern)
338
- message.clear!.clear
339
- @bson_empty ||= BSON::BSON_CODER.serialize({})
340
- message.put_binary(@bson_empty.to_s)
341
- message.unfinish!.array!(WRITE_COMMAND_ARG_KEY[op_type])
342
- end
343
-
344
- def batch_message_append(message, serialized_doc, write_concern)
345
- message.push_doc!(serialized_doc)
346
- end
347
-
348
- def batch_message_send(message, op_type, batch_docs, write_concern, continue_on_error)
349
- message.finish!
350
- request = BSON::OrderedHash[op_type, @name, :bson, message]
351
- request.merge!(:writeConcern => write_concern, :ordered => !continue_on_error)
352
- instrument(:insert, :database => @db.name, :collection => @name, :documents => batch_docs) do
353
- @db.command(request)
354
- end
355
- end
356
-
357
- def batch_write_max_sizes(write_concern)
358
- [MongoClient::COMMAND_HEADROOM, MongoClient::APPEND_HEADROOM, MongoClient::SERIALIZE_HEADROOM].collect{|h| @connection.max_bson_size + h}
359
- end
360
-
361
- end
362
-
363
- end
364
-