mongo 1.12.5 → 2.0.0.beta

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -1,87 +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
- # Wrapper class for Socket
17
- #
18
- # Emulates TCPSocket with operation and connection timeout
19
- # sans Timeout::timeout
20
- #
21
- class TCPSocket
22
- include SocketUtil
23
-
24
- def initialize(host, port, op_timeout=nil, connect_timeout=nil, opts={})
25
- @op_timeout = op_timeout
26
- @connect_timeout = connect_timeout
27
- @pid = Process.pid
28
- @auths = Set.new
29
-
30
- @socket = handle_connect(host, port)
31
- end
32
-
33
- def handle_connect(host, port)
34
- error = nil
35
- # Following python's lead (see PYTHON-356)
36
- family = host == 'localhost' ? Socket::AF_INET : Socket::AF_UNSPEC
37
- addr_info = Socket.getaddrinfo(host, nil, family, Socket::SOCK_STREAM)
38
- error = nil
39
- addr_info.each do |info|
40
- begin
41
- sock = Socket.new(info[4], Socket::SOCK_STREAM, 0)
42
- sock.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
43
- socket_address = Socket.pack_sockaddr_in(port, info[3])
44
- connect(sock, socket_address)
45
- return sock
46
- rescue IOError, SystemCallError => e
47
- error = e
48
- sock.close if sock
49
- end
50
- end
51
- raise error
52
- end
53
-
54
- def connect(socket, socket_address)
55
- if @connect_timeout
56
- Timeout::timeout(@connect_timeout, ConnectionTimeoutError) do
57
- socket.connect(socket_address)
58
- end
59
- else
60
- socket.connect(socket_address)
61
- end
62
- end
63
-
64
- def send(data)
65
- @socket.write(data)
66
- end
67
-
68
- def read(maxlen, buffer)
69
- # Block on data to read for @op_timeout seconds
70
- begin
71
- ready = IO.select([@socket], nil, [@socket], @op_timeout)
72
- unless ready
73
- raise OperationTimeout
74
- end
75
- rescue IOError
76
- raise ConnectionFailure
77
- end
78
-
79
- # Read data from socket
80
- begin
81
- @socket.sysread(maxlen, buffer)
82
- rescue SystemCallError, IOError => ex
83
- raise ConnectionFailure, ex
84
- end
85
- end
86
- end
87
- end
@@ -1,39 +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
- attr_accessor :auths
18
-
19
- # Wrapper class for Socket
20
- #
21
- # Emulates UNIXSocket with operation and connection timeout
22
- # sans Timeout::timeout
23
- #
24
- class UNIXSocket < TCPSocket
25
- def initialize(socket_path, port=:socket, op_timeout=nil, connect_timeout=nil, opts={})
26
- @op_timeout = op_timeout
27
- @connect_timeout = connect_timeout
28
- @pid = Process.pid
29
- @auths = Set.new
30
-
31
- @address = socket_path
32
- @port = :socket # purposely override input
33
-
34
- @socket_address = Socket.pack_sockaddr_un(@address)
35
- @socket = Socket.new(Socket::AF_UNIX, Socket::SOCK_STREAM, 0)
36
- connect(@socket, @socket_address)
37
- end
38
- end
39
- end
data/lib/mongo/db.rb DELETED
@@ -1,808 +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 MongoDB database.
18
- class DB
19
- include Mongo::WriteConcern
20
-
21
- SYSTEM_NAMESPACE_COLLECTION = 'system.namespaces'
22
- SYSTEM_INDEX_COLLECTION = 'system.indexes'
23
- SYSTEM_PROFILE_COLLECTION = 'system.profile'
24
- SYSTEM_USER_COLLECTION = 'system.users'
25
- SYSTEM_JS_COLLECTION = 'system.js'
26
- SYSTEM_COMMAND_COLLECTION = '$cmd'
27
- MAX_TIME_MS_CODE = 50
28
-
29
- PROFILE_LEVEL = {
30
- :off => 0,
31
- :slow_only => 1,
32
- :all => 2
33
- }
34
-
35
- # Counter for generating unique request ids.
36
- @@current_request_id = 0
37
-
38
- # Strict mode enforces collection existence checks. When +true+,
39
- # asking for a collection that does not exist, or trying to create a
40
- # collection that already exists, raises an error.
41
- #
42
- # Strict mode is disabled by default, but enabled (+true+) at any time.
43
- #
44
- # @deprecated Support for strict will be removed in version 2.0 of the driver.
45
- def strict=(value)
46
- unless ENV['TEST_MODE']
47
- warn "Support for strict mode has been deprecated and will be " +
48
- "removed in version 2.0 of the driver."
49
- end
50
- @strict = value
51
- end
52
-
53
- # Returns the value of the +strict+ flag.
54
- #
55
- # @deprecated Support for strict will be removed in version 2.0 of the driver.
56
- def strict?
57
- @strict
58
- end
59
-
60
- # The name of the database and the local write concern options.
61
- attr_reader :name, :write_concern
62
-
63
- # The Mongo::MongoClient instance connecting to the MongoDB server.
64
- attr_reader :client
65
-
66
- # for backward compatibility
67
- alias_method :connection, :client
68
-
69
- # The length of time that Collection.ensure_index should cache index calls
70
- attr_accessor :cache_time
71
-
72
- # Read Preference
73
- attr_accessor :read, :tag_sets, :acceptable_latency
74
-
75
- # Instances of DB are normally obtained by calling Mongo#db.
76
- #
77
- # @param [String] name the database name.
78
- # @param [Mongo::MongoClient] client a connection object pointing to MongoDB. Note
79
- # that databases are usually instantiated via the MongoClient class. See the examples below.
80
- #
81
- # @option opts [Boolean] :strict (False) [DEPRECATED] If true, collections existence checks are
82
- # performed during a number of relevant operations. See DB#collection, DB#create_collection and
83
- # DB#drop_collection.
84
- #
85
- # @option opts [Object, #create_pk(doc)] :pk (BSON::ObjectId) A primary key factory object,
86
- # which should take a hash and return a hash which merges the original hash with any primary key
87
- # fields the factory wishes to inject. (NOTE: if the object already has a primary key,
88
- # the factory should not inject a new key).
89
- #
90
- # @option opts [String, Integer, Symbol] :w (1) Set default number of nodes to which a write
91
- # should be acknowledged.
92
- # @option opts [Integer] :wtimeout (nil) Set replica set acknowledgement timeout.
93
- # @option opts [Boolean] :j (false) If true, block until write operations have been committed
94
- # to the journal. Cannot be used in combination with 'fsync'. Prior to MongoDB 2.6 this option was
95
- # ignored if the server was running without journaling. Starting with MongoDB 2.6, write operations will
96
- # fail with an exception if this option is used when the server is running without journaling.
97
- # @option opts [Boolean] :fsync (false) If true, and the server is running without journaling, blocks until
98
- # the server has synced all data files to disk. If the server is running with journaling, this acts the same as
99
- # the 'j' option, blocking until write operations have been committed to the journal.
100
- # Cannot be used in combination with 'j'.
101
- #
102
- # Notes on write concern:
103
- # These write concern options are propagated to Collection objects instantiated off of this DB. If no
104
- # options are provided, the default write concern set on this instance's MongoClient object will be used. This
105
- # default can be overridden upon instantiation of any collection by explicitly setting write concern options
106
- # on initialization or at the time of an operation.
107
- #
108
- # @option opts [Integer] :cache_time (300) Set the time that all ensure_index calls should cache the command.
109
-
110
- def initialize(name, client, opts={})
111
- # A database name of '$external' is permitted for some auth types
112
- Support.validate_db_name(name) unless name == '$external'
113
-
114
- @name = name
115
- @client = client
116
- @strict = opts[:strict]
117
- @pk_factory = opts[:pk]
118
-
119
- @write_concern = get_write_concern(opts, client)
120
-
121
- @read = opts[:read] || @client.read
122
- ReadPreference::validate(@read)
123
-
124
- @tag_sets = opts.fetch(:tag_sets, @client.tag_sets)
125
- @acceptable_latency = opts.fetch(:acceptable_latency,
126
- @client.acceptable_latency)
127
-
128
- @cache_time = opts[:cache_time] || 300 #5 minutes.
129
- end
130
-
131
- # Authenticate with the given username and password.
132
- #
133
- # @param username [String] The username.
134
- # @param password [String] The user's password. This is not required for
135
- # some authentication mechanisms.
136
- # @param save_auth [Boolean]
137
- # Save this authentication to the client object using
138
- # MongoClient#add_auth. This will ensure that the authentication will
139
- # be applied to all sockets and upon database reconnect.
140
- # @param source [String] Database with user credentials. This should be
141
- # used to authenticate against a database when the credentials exist
142
- # elsewhere.
143
- # @param mechanism [String] The authentication mechanism to be used.
144
- # @param extra [Hash] A optional hash of extra options to be stored with
145
- # the credential set.
146
- #
147
- # @note The ability to disable the save_auth option has been deprecated.
148
- # With save_auth=false specified, driver authentication behavior during
149
- # failovers and reconnections becomes unreliable. This option still
150
- # exists for API compatibility, but it no longer has any effect if
151
- # disabled and now always uses the default behavior (safe_auth=true).
152
- #
153
- # @raise [AuthenticationError] Raised if authentication fails.
154
- # @return [Boolean] The result of the authentication operation.
155
- def authenticate(username, password=nil, save_auth=nil, source=nil, mechanism=nil, extra=nil)
156
- warn "[DEPRECATED] Disabling the 'save_auth' option no longer has " +
157
- "any effect. Please see the API documentation for more details " +
158
- "on this change." unless save_auth.nil?
159
- @client.add_auth(self.name, username, password, source, mechanism, extra)
160
- true
161
- end
162
-
163
- # Deauthorizes use for this database for this client connection. Also removes
164
- # the saved authentication in the MongoClient class associated with this
165
- # database.
166
- #
167
- # @return [Boolean]
168
- def logout(opts={})
169
- @client.remove_auth(self.name)
170
- true
171
- end
172
-
173
- # Adds a stored Javascript function to the database which can executed
174
- # server-side in map_reduce, db.eval and $where clauses.
175
- #
176
- # @param [String] function_name
177
- # @param [String] code
178
- #
179
- # @return [String] the function name saved to the database
180
- def add_stored_function(function_name, code)
181
- self[SYSTEM_JS_COLLECTION].save(
182
- {
183
- "_id" => function_name,
184
- :value => BSON::Code.new(code)
185
- }
186
- )
187
- end
188
-
189
- # Removes stored Javascript function from the database. Returns
190
- # false if the function does not exist
191
- #
192
- # @param [String] function_name
193
- #
194
- # @return [Boolean]
195
- def remove_stored_function(function_name)
196
- return false unless self[SYSTEM_JS_COLLECTION].find_one({"_id" => function_name})
197
- self[SYSTEM_JS_COLLECTION].remove({"_id" => function_name}, :w => 1)
198
- end
199
-
200
- # Adds a user to this database for use with authentication. If the user already
201
- # exists in the system, the password and any additional fields provided in opts
202
- # will be updated.
203
- #
204
- # @param [String] username
205
- # @param [String] password
206
- # @param [Boolean] read_only
207
- # Create a read-only user.
208
- #
209
- # @param [Hash] opts
210
- # Optional fields for the user document (e.g. +userSource+, or +roles+)
211
- #
212
- # See {http://docs.mongodb.org/manual/reference/privilege-documents}
213
- # for more information.
214
- #
215
- # @note The use of the opts argument to provide or update additional fields
216
- # on the user document requires MongoDB >= 2.4.0
217
- #
218
- # @return [Hash] an object representing the user.
219
- def add_user(username, password=nil, read_only=false, opts={})
220
- user_info = command(:usersInfo => username)
221
- if user_info.key?('users') && !user_info['users'].empty?
222
- create_or_update_user(:updateUser, username, password, read_only, opts)
223
- else
224
- create_or_update_user(:createUser, username, password, read_only, opts)
225
- end
226
- # MongoDB >= 2.5.3 requires the use of commands to manage users.
227
- # "Command not found" error didn't return an error code (59) before
228
- # MongoDB 2.4.7 so we assume that a nil error code means the usersInfo
229
- # command doesn't exist and we should fall back to the legacy add user code.
230
- rescue OperationFailure => ex
231
- if Mongo::ErrorCode::COMMAND_NOT_FOUND_CODES.include?(ex.error_code)
232
- legacy_add_user(username, password, read_only, opts)
233
- elsif ex.error_code == Mongo::ErrorCode::UNAUTHORIZED
234
- # In MongoDB > 2.7 the localhost exception was narrowed, and the usersInfo
235
- # command is no longer allowed. In this case, add the first user.
236
- create_or_update_user(:createUser, username, password, read_only, opts)
237
- else
238
- raise ex
239
- end
240
- end
241
-
242
- # Remove the given user from this database. Returns false if the user
243
- # doesn't exist in the system.
244
- #
245
- # @param [String] username
246
- #
247
- # @return [Boolean]
248
- def remove_user(username)
249
- begin
250
- command(:dropUser => username)
251
- rescue OperationFailure => ex
252
- raise ex unless Mongo::ErrorCode::COMMAND_NOT_FOUND_CODES.include?(ex.error_code)
253
- response = self[SYSTEM_USER_COLLECTION].remove({:user => username}, :w => 1)
254
- response.key?('n') && response['n'] > 0 ? response : false
255
- end
256
- end
257
-
258
- # Get an array of collection names in this database.
259
- #
260
- # @return [Array]
261
- def collection_names
262
- if @client.wire_version_feature?(Mongo::MongoClient::MONGODB_3_0)
263
- names = collections_info.collect { |doc| doc['name'] || '' }
264
- names.delete_if do |name|
265
- name.index('$')
266
- end
267
- else
268
- legacy_collection_names
269
- end
270
- end
271
-
272
- # Get an array of Collection instances, one for each collection in this database.
273
- #
274
- # @return [Array<Mongo::Collection>]
275
- def collections
276
- collection_names.map do |name|
277
- Collection.new(name, self)
278
- end
279
- end
280
-
281
- # Get info on system namespaces (collections). This method returns
282
- # a cursor which can be iterated over. For each collection, a hash
283
- # will be yielded containing a 'name' string and, optionally, an 'options' hash.
284
- #
285
- # @param [String] coll_name return info for the specified collection only.
286
- #
287
- # @return [Array] List of collection info.
288
- def collections_info(coll_name=nil)
289
- if @client.wire_version_feature?(Mongo::MongoClient::MONGODB_3_0)
290
- cmd = BSON::OrderedHash[:listCollections, 1]
291
- cmd.merge!(:filter => { :name => coll_name }) if coll_name
292
- result = self.command(cmd, :cursor => {})
293
- if result.key?('cursor')
294
- cursor_info = result['cursor']
295
- pinned_pool = @client.pinned_pool
296
- pinned_pool = pinned_pool[:pool] if pinned_pool.respond_to?(:keys)
297
-
298
- seed = {
299
- :cursor_id => cursor_info['id'],
300
- :first_batch => cursor_info['firstBatch'],
301
- :pool => pinned_pool,
302
- :ns => cursor_info['ns']
303
- }
304
-
305
- Cursor.new(Collection.new('$cmd', self), seed).to_a
306
- else
307
- result['collections']
308
- end
309
- else
310
- legacy_collections_info(coll_name).to_a
311
- end
312
- end
313
-
314
- # Create a collection.
315
- #
316
- # new collection. If +strict+ is true, will raise an error if
317
- # collection +name+ already exists.
318
- #
319
- # @param [String, Symbol] name the name of the new collection.
320
- #
321
- # @option opts [Boolean] :capped (False) created a capped collection.
322
- #
323
- # @option opts [Integer] :size (Nil) If +capped+ is +true+,
324
- # specifies the maximum number of bytes for the capped collection.
325
- # If +false+, specifies the number of bytes allocated
326
- # for the initial extent of the collection.
327
- #
328
- # @option opts [Integer] :max (Nil) If +capped+ is +true+, indicates
329
- # the maximum number of records in a capped collection.
330
- #
331
- # @raise [MongoDBError] raised under two conditions:
332
- # either we're in +strict+ mode and the collection
333
- # already exists or collection creation fails on the server.
334
- #
335
- # @note Note that the options listed may be subset of those available.
336
- # Please see the MongoDB documentation for a full list of supported options by server version.
337
- #
338
- # @return [Mongo::Collection]
339
- def create_collection(name, opts={})
340
- name = name.to_s
341
- if strict? && collection_names.include?(name)
342
- raise MongoDBError, "Collection '#{name}' already exists. (strict=true)"
343
- end
344
-
345
- begin
346
- cmd = BSON::OrderedHash.new
347
- cmd[:create] = name
348
- doc = command(cmd.merge(opts || {}))
349
- return Collection.new(name, self, :pk => @pk_factory) if ok?(doc)
350
- rescue OperationFailure => e
351
- return Collection.new(name, self, :pk => @pk_factory) if e.message =~ /exists/
352
- raise e
353
- end
354
- raise MongoDBError, "Error creating collection: #{doc.inspect}"
355
- end
356
-
357
- # Get a collection by name.
358
- #
359
- # @param [String, Symbol] name the collection name.
360
- # @param [Hash] opts any valid options that can be passed to Collection#new.
361
- #
362
- # @raise [MongoDBError] if collection does not already exist and we're in
363
- # +strict+ mode.
364
- #
365
- # @return [Mongo::Collection]
366
- def collection(name, opts={})
367
- if strict? && !collection_names.include?(name.to_s)
368
- raise MongoDBError, "Collection '#{name}' doesn't exist. (strict=true)"
369
- else
370
- opts = opts.dup
371
- opts.merge!(:pk => @pk_factory) unless opts[:pk]
372
- Collection.new(name, self, opts)
373
- end
374
- end
375
- alias_method :[], :collection
376
-
377
- # Drop a collection by +name+.
378
- #
379
- # @param [String, Symbol] name
380
- #
381
- # @return [Boolean] +true+ on success or +false+ if the collection name doesn't exist.
382
- def drop_collection(name)
383
- return false if strict? && !collection_names.include?(name.to_s)
384
- begin
385
- ok?(command(:drop => name))
386
- rescue OperationFailure
387
- false
388
- end
389
- end
390
-
391
- # Run the getlasterror command with the specified replication options.
392
- #
393
- # @option opts [Boolean] :fsync (false)
394
- # @option opts [Integer] :w (nil)
395
- # @option opts [Integer] :wtimeout (nil)
396
- # @option opts [Boolean] :j (false)
397
- #
398
- # @return [Hash] the entire response to getlasterror.
399
- #
400
- # @raise [MongoDBError] if the operation fails.
401
- def get_last_error(opts={})
402
- cmd = BSON::OrderedHash.new
403
- cmd[:getlasterror] = 1
404
- cmd.merge!(opts)
405
- doc = command(cmd, :check_response => false)
406
- raise MongoDBError, "Error retrieving last error: #{doc.inspect}" unless ok?(doc)
407
- doc
408
- end
409
-
410
- # Return +true+ if an error was caused by the most recently executed
411
- # database operation.
412
- #
413
- # @return [Boolean]
414
- def error?
415
- get_last_error['err'] != nil
416
- end
417
-
418
- # Get the most recent error to have occurred on this database.
419
- #
420
- # This command only returns errors that have occurred since the last call to
421
- # DB#reset_error_history - returns +nil+ if there is no such error.
422
- #
423
- # @return [String, Nil] the text of the error or +nil+ if no error has occurred.
424
- def previous_error
425
- error = command(:getpreverror => 1)
426
- error["err"] ? error : nil
427
- end
428
-
429
- # Reset the error history of this database
430
- #
431
- # Calls to DB#previous_error will only return errors that have occurred
432
- # since the most recent call to this method.
433
- #
434
- # @return [Hash]
435
- def reset_error_history
436
- command(:reseterror => 1)
437
- end
438
-
439
- # Dereference a DBRef, returning the document it points to.
440
- #
441
- # @param [Mongo::DBRef] dbref
442
- #
443
- # @return [Hash] the document indicated by the db reference.
444
- #
445
- # @see http://www.mongodb.org/display/DOCS/DB+Ref MongoDB DBRef spec.
446
- def dereference(dbref)
447
- collection(dbref.namespace).find_one("_id" => dbref.object_id)
448
- end
449
-
450
- # Evaluate a JavaScript expression in MongoDB.
451
- #
452
- # @param [String, Code] code a JavaScript expression to evaluate server-side.
453
- # @param [Integer, Hash] args any additional argument to be passed to the +code+ expression when
454
- # it's run on the server.
455
- #
456
- # @note the eval command is deprecated in MongoDB 3.0 and will be removed in a future server version.
457
- #
458
- # @return [String] the return value of the function.
459
- def eval(code, *args)
460
- unless code.is_a?(BSON::Code)
461
- code = BSON::Code.new(code)
462
- end
463
-
464
- cmd = BSON::OrderedHash.new
465
- cmd[:$eval] = code
466
- cmd.merge!(args.pop) if args.last.respond_to?(:keys) && args.last.key?(:nolock)
467
- cmd[:args] = args
468
- doc = command(cmd)
469
- doc['retval']
470
- end
471
-
472
- # Rename a collection.
473
- #
474
- # @param [String] from original collection name.
475
- # @param [String] to new collection name.
476
- #
477
- # @return [True] returns +true+ on success.
478
- #
479
- # @raise MongoDBError if there's an error renaming the collection.
480
- def rename_collection(from, to)
481
- cmd = BSON::OrderedHash.new
482
- cmd[:renameCollection] = "#{@name}.#{from}"
483
- cmd[:to] = "#{@name}.#{to}"
484
- doc = DB.new('admin', @client).command(cmd, :check_response => false)
485
- ok?(doc) || raise(MongoDBError, "Error renaming collection: #{doc.inspect}")
486
- end
487
-
488
- # Drop an index from a given collection. Normally called from
489
- # Collection#drop_index or Collection#drop_indexes.
490
- #
491
- # @param [String] collection_name
492
- # @param [String] index_name
493
- #
494
- # @return [True] returns +true+ on success.
495
- #
496
- # @raise MongoDBError if there's an error dropping the index.
497
- def drop_index(collection_name, index_name)
498
- cmd = BSON::OrderedHash.new
499
- cmd[:deleteIndexes] = collection_name
500
- cmd[:index] = index_name.to_s
501
- doc = command(cmd, :check_response => false)
502
- ok?(doc) || raise(MongoDBError, "Error with drop_index command: #{doc.inspect}")
503
- end
504
-
505
- # Get information on the indexes for the given collection.
506
- # Normally called by Collection#index_information.
507
- #
508
- # @param [String] collection_name
509
- #
510
- # @return [Hash] keys are index names and the values are lists of [key, type] pairs
511
- # defining the index.
512
- def index_information(collection_name)
513
- if @client.wire_version_feature?(Mongo::MongoClient::MONGODB_3_0)
514
- result = self.command({ :listIndexes => collection_name }, :cursor => {})
515
- if result.key?('cursor')
516
- cursor_info = result['cursor']
517
- pinned_pool = @client.pinned_pool
518
- pinned_pool = pinned_pool[:pool] if pinned_pool.respond_to?(:keys)
519
-
520
- seed = {
521
- :cursor_id => cursor_info['id'],
522
- :first_batch => cursor_info['firstBatch'],
523
- :pool => pinned_pool,
524
- :ns => cursor_info['ns']
525
- }
526
-
527
- indexes = Cursor.new(Collection.new('$cmd', self), seed).to_a
528
- else
529
- indexes = result['indexes']
530
- end
531
- else
532
- indexes = legacy_list_indexes(collection_name)
533
- end
534
- indexes.reduce({}) do |info, index|
535
- info.merge!(index['name'] => index)
536
- end
537
- end
538
-
539
- # Return stats on this database. Uses MongoDB's dbstats command.
540
- #
541
- # @return [Hash]
542
- def stats
543
- self.command(:dbstats => 1)
544
- end
545
-
546
- # Return +true+ if the supplied +doc+ contains an 'ok' field with the value 1.
547
- #
548
- # @param [Hash] doc
549
- #
550
- # @return [Boolean]
551
- def ok?(doc)
552
- Mongo::Support.ok?(doc)
553
- end
554
-
555
- # Send a command to the database.
556
- #
557
- # Note: DB commands must start with the "command" key. For this reason,
558
- # any selector containing more than one key must be an OrderedHash.
559
- #
560
- # Note also that a command in MongoDB is just a kind of query
561
- # that occurs on the system command collection ($cmd). Examine this method's implementation
562
- # to see how it works.
563
- #
564
- # @param [OrderedHash, Hash] selector an OrderedHash, or a standard Hash with just one
565
- # key, specifying the command to be performed. In Ruby 1.9 and above, OrderedHash isn't necessary
566
- # because hashes are ordered by default.
567
- #
568
- # @option opts [Boolean] :check_response (true) If +true+, raises an exception if the
569
- # command fails.
570
- # @option opts [Socket] :socket a socket to use for sending the command. This is mainly for internal use.
571
- # @option opts [:primary, :secondary] :read Read preference for this command. See Collection#find for
572
- # more details.
573
- # @option opts [String] :comment (nil) a comment to include in profiling logs
574
- # @option opts [Boolean] :compile_regex (true) whether BSON regex objects should be compiled into Ruby regexes.
575
- # If false, a BSON::Regex object will be returned instead.
576
- #
577
- # @return [Hash]
578
- def command(selector, opts={})
579
- raise MongoArgumentError, "Command must be given a selector" unless selector.respond_to?(:keys) && !selector.empty?
580
-
581
- opts = opts.dup
582
- # deletes :check_response and returns the value, if nil defaults to the block result
583
- check_response = opts.delete(:check_response) { true }
584
-
585
- # build up the command hash
586
- command = opts.key?(:socket) ? { :socket => opts.delete(:socket) } : {}
587
- command.merge!(:comment => opts.delete(:comment)) if opts.key?(:comment)
588
- command.merge!(:compile_regex => opts.delete(:compile_regex)) if opts.key?(:compile_regex)
589
- command[:limit] = -1
590
- command[:read] = Mongo::ReadPreference::cmd_read_pref(opts.delete(:read), selector) if opts.key?(:read)
591
-
592
- if RUBY_VERSION < '1.9' && selector.class != BSON::OrderedHash
593
- if selector.keys.length > 1
594
- raise MongoArgumentError, "DB#command requires an OrderedHash when hash contains multiple keys"
595
- end
596
- if opts.keys.size > 0
597
- # extra opts will be merged into the selector, so make sure it's an OH in versions < 1.9
598
- selector = selector.dup
599
- selector = BSON::OrderedHash.new.merge!(selector)
600
- end
601
- end
602
-
603
- # arbitrary opts are merged into the selector
604
- command[:selector] = selector.merge!(opts)
605
-
606
- begin
607
- result = Cursor.new(system_command_collection, command).next_document
608
- rescue OperationFailure => ex
609
- if check_response
610
- raise ex.class.new("Database command '#{selector.keys.first}' failed: #{ex.message}", ex.error_code, ex.result)
611
- else
612
- result = ex.result
613
- end
614
- end
615
-
616
- raise OperationFailure,
617
- "Database command '#{selector.keys.first}' failed: returned null." unless result
618
-
619
- if check_response && (!ok?(result) || result['writeErrors'] || result['writeConcernError'])
620
- message = "Database command '#{selector.keys.first}' failed: ("
621
- message << result.map do |key, value|
622
- "#{key}: '#{value}'"
623
- end.join('; ')
624
- message << ').'
625
- code = result['code'] || result['assertionCode']
626
- if result['writeErrors']
627
- code = result['writeErrors'].first['code']
628
- end
629
- raise ExecutionTimeout.new(message, code, result) if code == MAX_TIME_MS_CODE
630
- raise OperationFailure.new(message, code, result)
631
- end
632
-
633
- result
634
- end
635
-
636
- # A shortcut returning db plus dot plus collection name.
637
- #
638
- # @param [String] collection_name
639
- #
640
- # @return [String]
641
- def full_collection_name(collection_name)
642
- "#{@name}.#{collection_name}"
643
- end
644
-
645
- # The primary key factory object (or +nil+).
646
- #
647
- # @return [Object, Nil]
648
- def pk_factory
649
- @pk_factory
650
- end
651
-
652
- # Specify a primary key factory if not already set.
653
- #
654
- # @raise [MongoArgumentError] if the primary key factory has already been set.
655
- def pk_factory=(pk_factory)
656
- raise MongoArgumentError,
657
- "Cannot change primary key factory once it's been set" if @pk_factory
658
-
659
- @pk_factory = pk_factory
660
- end
661
-
662
- # Return the current database profiling level. If profiling is enabled, you can
663
- # get the results using DB#profiling_info.
664
- #
665
- # @return [Symbol] :off, :slow_only, or :all
666
- def profiling_level
667
- cmd = BSON::OrderedHash.new
668
- cmd[:profile] = -1
669
- doc = command(cmd, :check_response => false)
670
-
671
- raise "Error with profile command: #{doc.inspect}" unless ok?(doc)
672
-
673
- level_sym = PROFILE_LEVEL.invert[doc['was'].to_i]
674
- raise "Error: illegal profiling level value #{doc['was']}" unless level_sym
675
- level_sym
676
- end
677
-
678
- # Set this database's profiling level. If profiling is enabled, you can
679
- # get the results using DB#profiling_info.
680
- #
681
- # @param [Symbol] level acceptable options are +:off+, +:slow_only+, or +:all+.
682
- def profiling_level=(level)
683
- cmd = BSON::OrderedHash.new
684
- cmd[:profile] = PROFILE_LEVEL[level]
685
- doc = command(cmd, :check_response => false)
686
- ok?(doc) || raise(MongoDBError, "Error with profile command: #{doc.inspect}")
687
- end
688
-
689
- # Get the current profiling information.
690
- #
691
- # @return [Array] a list of documents containing profiling information.
692
- def profiling_info
693
- Cursor.new(Collection.new(SYSTEM_PROFILE_COLLECTION, self), :selector => {}).to_a
694
- end
695
-
696
- # Validate a named collection.
697
- #
698
- # @param [String] name the collection name.
699
- #
700
- # @return [Hash] validation information.
701
- #
702
- # @raise [MongoDBError] if the command fails or there's a problem with the validation
703
- # data, or if the collection is invalid.
704
- def validate_collection(name)
705
- cmd = BSON::OrderedHash.new
706
- cmd[:validate] = name
707
- cmd[:full] = true
708
- doc = command(cmd, :check_response => false)
709
-
710
- raise MongoDBError, "Error with validate command: #{doc.inspect}" unless ok?(doc)
711
-
712
- if (doc.has_key?('valid') && !doc['valid']) || (doc['result'] =~ /\b(exception|corrupt)\b/i)
713
- raise MongoDBError, "Error: invalid collection #{name}: #{doc.inspect}"
714
- end
715
- doc
716
- end
717
-
718
- private
719
-
720
- def system_command_collection
721
- Collection.new(SYSTEM_COMMAND_COLLECTION, self)
722
- end
723
-
724
- # Create a new user.
725
- #
726
- # @param username [String] The username.
727
- # @param password [String] The user's password.
728
- # @param read_only [Boolean] Create a read-only user (deprecated in MongoDB >= 2.6)
729
- # @param opts [Hash]
730
- #
731
- # @private
732
- def create_or_update_user(command, username, password, read_only, opts)
733
- if read_only || !opts.key?(:roles)
734
- warn "Creating a user with the read_only option or without roles is " +
735
- "deprecated in MongoDB >= 2.6"
736
- end
737
-
738
- # The password is always salted and hashed by the driver.
739
- if opts.key?(:digestPassword)
740
- raise MongoArgumentError,
741
- "The digestPassword option is not available via DB#add_user. " +
742
- "Use DB#command(:createUser => ...) instead for this option."
743
- end
744
-
745
- opts = opts.dup
746
- pwd = Mongo::Authentication.hash_password(username, password) if password
747
- cmd_opts = pwd ? { :pwd => pwd } : {}
748
- # specify that the server shouldn't digest the password because the driver does
749
- cmd_opts[:digestPassword] = false
750
- unless opts.key?(:roles)
751
- if name == 'admin'
752
- roles = read_only ? ['readAnyDatabase'] : ['root']
753
- else
754
- roles = read_only ? ['read'] : ["dbOwner"]
755
- end
756
- cmd_opts[:roles] = roles
757
- end
758
- cmd_opts[:writeConcern] =
759
- opts.key?(:writeConcern) ? opts.delete(:writeConcern) : { :w => 1 }
760
- cmd_opts.merge!(opts)
761
- command({ command => username }, cmd_opts)
762
- end
763
-
764
- # Create a user in MongoDB versions < 2.5.3.
765
- # Called by #add_user if the 'usersInfo' command fails.
766
- #
767
- # @param username [String] The username.
768
- # @param password [String] (nil) The user's password.
769
- # @param read_only [Boolean] (false) Create a read-only user.
770
- # @param opts [Hash]
771
- #
772
- # @private
773
- def legacy_add_user(username, password=nil, read_only=false, opts={})
774
- users = self[SYSTEM_USER_COLLECTION]
775
- user = users.find_one(:user => username) || {:user => username}
776
- user['pwd'] =
777
- Mongo::Authentication.hash_password(username, password) if password
778
- user['readOnly'] = true if read_only
779
- user.merge!(opts)
780
- begin
781
- users.save(user)
782
- rescue OperationFailure => ex
783
- # adding first admin user fails GLE in MongoDB 2.2
784
- raise ex unless ex.message =~ /login/
785
- end
786
- user
787
- end
788
-
789
- def legacy_list_indexes(collection_name)
790
- sel = {:ns => full_collection_name(collection_name)}
791
- Cursor.new(Collection.new(SYSTEM_INDEX_COLLECTION, self), :selector => sel)
792
- end
793
-
794
- def legacy_collections_info(coll_name=nil)
795
- selector = {}
796
- selector[:name] = full_collection_name(coll_name) if coll_name
797
- Cursor.new(Collection.new(SYSTEM_NAMESPACE_COLLECTION, self), :selector => selector)
798
- end
799
-
800
- def legacy_collection_names
801
- names = legacy_collections_info.collect { |doc| doc['name'] || '' }
802
- names = names.delete_if do |name|
803
- name.index(@name).nil? || name.index('$')
804
- end
805
- names.map {|name| name.sub(@name + '.', '')}
806
- end
807
- end
808
- end