mongo 1.12.5 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (475) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/CONTRIBUTING.md +64 -0
  4. data/LICENSE +1 -1
  5. data/README.md +21 -126
  6. data/Rakefile +39 -21
  7. data/bin/mongo_console +6 -38
  8. data/lib/mongo/address/ipv4.rb +85 -0
  9. data/lib/mongo/address/ipv6.rb +85 -0
  10. data/lib/mongo/address/unix.rb +76 -0
  11. data/lib/mongo/address.rb +111 -0
  12. data/lib/mongo/auth/cr/conversation.rb +119 -0
  13. data/lib/mongo/auth/cr.rb +44 -0
  14. data/lib/mongo/auth/executable.rb +52 -0
  15. data/lib/mongo/auth/ldap/conversation.rb +92 -0
  16. data/lib/mongo/auth/ldap.rb +48 -0
  17. data/lib/mongo/auth/roles.rb +104 -0
  18. data/lib/mongo/auth/scram/conversation.rb +450 -0
  19. data/lib/mongo/auth/scram.rb +53 -0
  20. data/lib/mongo/auth/user/view.rb +102 -0
  21. data/lib/mongo/auth/user.rb +159 -0
  22. data/lib/mongo/auth/x509/conversation.rb +92 -0
  23. data/lib/mongo/auth/x509.rb +48 -0
  24. data/lib/mongo/auth.rb +108 -0
  25. data/lib/mongo/bulk_write/bulk_writable.rb +191 -0
  26. data/lib/mongo/bulk_write/deletable.rb +60 -0
  27. data/lib/mongo/bulk_write/insertable.rb +52 -0
  28. data/lib/mongo/bulk_write/ordered_bulk_write.rb +48 -0
  29. data/lib/mongo/bulk_write/replacable.rb +57 -0
  30. data/lib/mongo/bulk_write/unordered_bulk_write.rb +46 -0
  31. data/lib/mongo/bulk_write/updatable.rb +68 -0
  32. data/lib/mongo/bulk_write.rb +52 -0
  33. data/lib/mongo/client.rb +246 -0
  34. data/lib/mongo/cluster/topology/replica_set.rb +160 -0
  35. data/lib/mongo/cluster/topology/sharded.rb +132 -0
  36. data/lib/mongo/cluster/topology/standalone.rb +132 -0
  37. data/lib/mongo/cluster/topology/unknown.rb +155 -0
  38. data/lib/mongo/cluster/topology.rb +60 -0
  39. data/lib/mongo/cluster.rb +203 -0
  40. data/lib/mongo/collection/view/aggregation.rb +108 -0
  41. data/lib/mongo/collection/view/explainable.rb +49 -0
  42. data/lib/mongo/collection/view/immutable.rb +43 -0
  43. data/lib/mongo/collection/view/iterable.rb +48 -0
  44. data/lib/mongo/collection/view/map_reduce.rb +191 -0
  45. data/lib/mongo/collection/view/readable.rb +363 -0
  46. data/lib/mongo/collection/view/writable.rb +185 -0
  47. data/lib/mongo/collection/view.rb +169 -0
  48. data/lib/mongo/collection.rb +130 -1101
  49. data/lib/mongo/cursor.rb +78 -681
  50. data/lib/mongo/database/view.rb +101 -0
  51. data/lib/mongo/database.rb +224 -0
  52. data/lib/mongo/error/bulk_write_error.rb +41 -0
  53. data/lib/mongo/error/invalid_bulk_operation.rb +36 -0
  54. data/lib/mongo/error/invalid_bulk_operation_type.rb +36 -0
  55. data/lib/mongo/error/invalid_collection_name.rb +39 -0
  56. data/lib/mongo/error/invalid_database_name.rb +39 -0
  57. data/{test/replica_set/ssl_test.rb → lib/mongo/error/invalid_document.rb} +21 -14
  58. data/lib/mongo/error/invalid_file.rb +38 -0
  59. data/lib/mongo/error/invalid_nonce.rb +46 -0
  60. data/lib/mongo/error/invalid_replacement_document.rb +39 -0
  61. data/lib/mongo/error/invalid_signature.rb +47 -0
  62. data/{test/functional/ssl_test.rb → lib/mongo/error/invalid_update_document.rb} +22 -12
  63. data/lib/mongo/error/max_bson_size.rb +40 -0
  64. data/lib/mongo/error/max_message_size.rb +42 -0
  65. data/{test/functional/db_connection_test.rb → lib/mongo/error/multi_index_drop.rb} +17 -8
  66. data/lib/mongo/{utils.rb → error/need_primary_server.rb} +10 -6
  67. data/lib/mongo/{connection.rb → error/operation_failure.rb} +10 -6
  68. data/lib/mongo/error/parser.rb +77 -0
  69. data/lib/mongo/{connection/socket.rb → error/socket_error.rb} +10 -5
  70. data/lib/mongo/error/socket_timeout_error.rb +23 -0
  71. data/lib/mongo/error/unsupported_features.rb +43 -0
  72. data/lib/mongo/error.rb +82 -0
  73. data/lib/mongo/event/listeners.rb +63 -0
  74. data/lib/mongo/event/primary_elected.rb +53 -0
  75. data/lib/mongo/event/publisher.rb +42 -0
  76. data/lib/mongo/event/server_added.rb +53 -0
  77. data/lib/mongo/event/server_removed.rb +53 -0
  78. data/lib/mongo/event/subscriber.rb +41 -0
  79. data/lib/mongo/event.rb +40 -0
  80. data/lib/mongo/grid/file/chunk.rb +184 -0
  81. data/lib/mongo/grid/file/metadata.rb +229 -0
  82. data/lib/mongo/grid/file.rb +106 -0
  83. data/lib/mongo/grid/fs.rb +149 -0
  84. data/lib/mongo/{gridfs.rb → grid.rb} +3 -5
  85. data/lib/mongo/index/view.rb +261 -0
  86. data/lib/mongo/index.rb +64 -0
  87. data/lib/mongo/loggable.rb +126 -0
  88. data/lib/mongo/logger.rb +132 -0
  89. data/lib/mongo/operation/aggregate/result.rb +88 -0
  90. data/lib/mongo/operation/aggregate.rb +100 -0
  91. data/lib/mongo/operation/command.rb +62 -0
  92. data/lib/mongo/operation/executable.rb +105 -0
  93. data/lib/mongo/operation/kill_cursors.rb +39 -0
  94. data/lib/mongo/operation/limited.rb +37 -0
  95. data/lib/mongo/operation/list_collections/result.rb +114 -0
  96. data/lib/mongo/operation/list_indexes/result.rb +118 -0
  97. data/lib/mongo/operation/map_reduce/result.rb +122 -0
  98. data/lib/mongo/operation/map_reduce.rb +96 -0
  99. data/lib/mongo/operation/read/collections_info.rb +67 -0
  100. data/lib/mongo/operation/read/get_more.rb +71 -0
  101. data/lib/mongo/operation/read/indexes.rb +68 -0
  102. data/lib/mongo/operation/read/list_collections.rb +75 -0
  103. data/lib/mongo/operation/read/list_indexes.rb +77 -0
  104. data/lib/mongo/operation/read/query.rb +71 -0
  105. data/lib/mongo/{functional.rb → operation/read.rb} +7 -7
  106. data/lib/mongo/operation/read_preferrable.rb +34 -0
  107. data/lib/mongo/operation/result.rb +259 -0
  108. data/lib/mongo/operation/specifiable.rb +397 -0
  109. data/lib/mongo/operation/write/bulk/bulk_delete/result.rb +75 -0
  110. data/lib/mongo/operation/write/bulk/bulk_delete.rb +144 -0
  111. data/lib/mongo/operation/write/bulk/bulk_insert/result.rb +68 -0
  112. data/lib/mongo/operation/write/bulk/bulk_insert.rb +129 -0
  113. data/lib/mongo/operation/write/bulk/bulk_mergable.rb +67 -0
  114. data/lib/mongo/operation/write/bulk/bulk_update/result.rb +162 -0
  115. data/lib/mongo/operation/write/bulk/bulk_update.rb +153 -0
  116. data/lib/mongo/operation/write/bulk/legacy_bulk_mergable.rb +83 -0
  117. data/lib/mongo/operation/write/bulk.rb +17 -0
  118. data/lib/mongo/operation/write/command/create_index.rb +50 -0
  119. data/lib/mongo/operation/write/command/create_user.rb +43 -0
  120. data/lib/mongo/operation/write/command/delete.rb +56 -0
  121. data/lib/mongo/operation/write/command/drop_index.rb +51 -0
  122. data/lib/mongo/operation/write/command/insert.rb +55 -0
  123. data/lib/mongo/operation/write/command/remove_user.rb +42 -0
  124. data/lib/mongo/operation/write/command/update.rb +60 -0
  125. data/lib/mongo/operation/write/command/writable.rb +61 -0
  126. data/lib/mongo/operation/write/command.rb +22 -0
  127. data/lib/mongo/operation/write/create_index.rb +89 -0
  128. data/lib/mongo/operation/write/create_user.rb +75 -0
  129. data/lib/mongo/operation/write/delete/result.rb +40 -0
  130. data/lib/mongo/operation/write/delete.rb +93 -0
  131. data/lib/mongo/operation/write/drop_index.rb +62 -0
  132. data/lib/mongo/{utils/thread_local_variable_manager.rb → operation/write/insert/result.rb} +15 -8
  133. data/lib/mongo/operation/write/insert.rb +90 -0
  134. data/lib/mongo/operation/write/remove_user.rb +70 -0
  135. data/lib/mongo/operation/write/update/result.rb +160 -0
  136. data/lib/mongo/operation/write/update.rb +103 -0
  137. data/lib/mongo/{connection/socket/socket_util.rb → operation/write.rb} +10 -24
  138. data/lib/mongo/operation.rb +25 -0
  139. data/lib/mongo/options/mapper.rb +78 -0
  140. data/lib/mongo/options.rb +15 -0
  141. data/lib/mongo/protocol/bit_vector.rb +61 -0
  142. data/lib/mongo/protocol/delete.rb +94 -0
  143. data/lib/mongo/protocol/get_more.rb +99 -0
  144. data/lib/mongo/protocol/insert.rb +99 -0
  145. data/lib/mongo/protocol/kill_cursors.rb +74 -0
  146. data/lib/mongo/protocol/message.rb +252 -0
  147. data/lib/mongo/protocol/query.rb +147 -0
  148. data/lib/mongo/protocol/reply.rb +72 -0
  149. data/lib/mongo/protocol/serializers.rb +180 -0
  150. data/lib/mongo/protocol/update.rb +111 -0
  151. data/lib/mongo/protocol.rb +15 -0
  152. data/lib/mongo/server/connectable.rb +110 -0
  153. data/lib/mongo/server/connection.rb +134 -0
  154. data/lib/mongo/server/connection_pool/queue.rb +182 -0
  155. data/lib/mongo/server/connection_pool.rb +141 -0
  156. data/lib/mongo/server/context.rb +66 -0
  157. data/lib/mongo/server/description/features.rb +85 -0
  158. data/lib/mongo/server/description/inspector/primary_elected.rb +58 -0
  159. data/lib/mongo/server/description/inspector/server_added.rb +59 -0
  160. data/lib/mongo/server/description/inspector/server_removed.rb +59 -0
  161. data/lib/mongo/server/description/inspector.rb +79 -0
  162. data/lib/mongo/server/description.rb +450 -0
  163. data/lib/mongo/server/monitor/connection.rb +89 -0
  164. data/lib/mongo/server/monitor.rb +176 -0
  165. data/lib/mongo/server.rb +163 -0
  166. data/lib/mongo/server_selector/nearest.rb +94 -0
  167. data/lib/mongo/server_selector/primary.rb +88 -0
  168. data/lib/mongo/server_selector/primary_preferred.rb +94 -0
  169. data/lib/mongo/server_selector/secondary.rb +91 -0
  170. data/lib/mongo/server_selector/secondary_preferred.rb +96 -0
  171. data/lib/mongo/server_selector/selectable.rb +209 -0
  172. data/lib/mongo/server_selector.rb +81 -0
  173. data/lib/mongo/socket/ssl.rb +130 -0
  174. data/lib/mongo/socket/tcp.rb +69 -0
  175. data/lib/mongo/socket/unix.rb +64 -0
  176. data/lib/mongo/socket.rb +179 -0
  177. data/lib/mongo/uri.rb +504 -0
  178. data/lib/mongo/version.rb +21 -0
  179. data/lib/mongo/write_concern/acknowledged.rb +52 -0
  180. data/lib/mongo/write_concern/normalizable.rb +51 -0
  181. data/lib/mongo/write_concern/unacknowledged.rb +55 -0
  182. data/lib/mongo/write_concern.rb +99 -0
  183. data/lib/mongo.rb +24 -82
  184. data/mongo.gemspec +17 -14
  185. data/spec/certificates/ca.pem +17 -0
  186. data/spec/certificates/client.pem +101 -0
  187. data/spec/certificates/crl.pem +10 -0
  188. data/spec/certificates/crl_client_revoked.pem +12 -0
  189. data/spec/certificates/password_protected.pem +51 -0
  190. data/spec/certificates/server.pem +34 -0
  191. data/spec/mongo/address/ipv4_spec.rb +74 -0
  192. data/spec/mongo/address/ipv6_spec.rb +74 -0
  193. data/spec/mongo/address/unix_spec.rb +30 -0
  194. data/spec/mongo/address_spec.rb +206 -0
  195. data/spec/mongo/auth/cr_spec.rb +59 -0
  196. data/spec/mongo/auth/ldap_spec.rb +40 -0
  197. data/spec/mongo/auth/scram/conversation_spec.rb +197 -0
  198. data/spec/mongo/auth/scram_spec.rb +55 -0
  199. data/spec/mongo/auth/user/view_spec.rb +76 -0
  200. data/spec/mongo/auth/user_spec.rb +190 -0
  201. data/spec/mongo/auth/x509_spec.rb +40 -0
  202. data/spec/mongo/auth_spec.rb +65 -0
  203. data/spec/mongo/bulk/bulk_write_spec.rb +262 -0
  204. data/spec/mongo/client_spec.rb +564 -0
  205. data/spec/mongo/cluster/topology/replica_set_spec.rb +101 -0
  206. data/spec/mongo/cluster/topology/sharded_spec.rb +74 -0
  207. data/spec/mongo/cluster/topology/standalone_spec.rb +79 -0
  208. data/spec/mongo/cluster/topology_spec.rb +65 -0
  209. data/spec/mongo/cluster_spec.rb +129 -0
  210. data/spec/mongo/collection/view/aggregation_spec.rb +148 -0
  211. data/spec/mongo/collection/view/explainable_spec.rb +32 -0
  212. data/spec/mongo/collection/view/map_reduce_spec.rb +242 -0
  213. data/spec/mongo/collection/view/readable_spec.rb +603 -0
  214. data/spec/mongo/collection/view/writable_spec.rb +679 -0
  215. data/spec/mongo/collection/view_spec.rb +530 -0
  216. data/spec/mongo/collection_spec.rb +362 -0
  217. data/spec/mongo/crud_spec.rb +42 -0
  218. data/spec/mongo/cursor_spec.rb +295 -0
  219. data/spec/mongo/database_spec.rb +302 -0
  220. data/spec/mongo/error/parser_spec.rb +119 -0
  221. data/spec/mongo/event/publisher_spec.rb +50 -0
  222. data/spec/mongo/event/subscriber_spec.rb +34 -0
  223. data/spec/mongo/grid/file/chunk_spec.rb +226 -0
  224. data/spec/mongo/grid/file/metadata_spec.rb +92 -0
  225. data/spec/mongo/grid/file_spec.rb +172 -0
  226. data/spec/mongo/grid/fs_spec.rb +129 -0
  227. data/spec/mongo/index/view_spec.rb +330 -0
  228. data/spec/mongo/loggable_spec.rb +62 -0
  229. data/spec/mongo/logger_spec.rb +97 -0
  230. data/spec/mongo/operation/aggregate/result_spec.rb +80 -0
  231. data/spec/mongo/operation/aggregate_spec.rb +127 -0
  232. data/spec/mongo/operation/command_spec.rb +98 -0
  233. data/spec/mongo/operation/kill_cursors_spec.rb +66 -0
  234. data/spec/mongo/operation/limited_spec.rb +50 -0
  235. data/spec/mongo/operation/map_reduce_spec.rb +143 -0
  236. data/spec/mongo/operation/read/collections_info_spec.rb +40 -0
  237. data/spec/mongo/operation/read/get_more_spec.rb +81 -0
  238. data/spec/mongo/operation/read/indexes_spec.rb +31 -0
  239. data/spec/mongo/operation/read/query_spec.rb +84 -0
  240. data/spec/mongo/operation/result_spec.rb +275 -0
  241. data/spec/mongo/operation/specifiable_spec.rb +53 -0
  242. data/spec/mongo/operation/write/bulk_delete_spec.rb +235 -0
  243. data/spec/mongo/operation/write/bulk_insert_spec.rb +235 -0
  244. data/spec/mongo/operation/write/bulk_update_spec.rb +236 -0
  245. data/spec/mongo/operation/write/command/delete_spec.rb +103 -0
  246. data/spec/mongo/operation/write/command/insert_spec.rb +103 -0
  247. data/spec/mongo/operation/write/command/update_spec.rb +109 -0
  248. data/spec/mongo/operation/write/create_index_spec.rb +63 -0
  249. data/spec/mongo/operation/write/create_user_spec.rb +44 -0
  250. data/spec/mongo/operation/write/delete_spec.rb +186 -0
  251. data/spec/mongo/operation/write/drop_index_spec.rb +51 -0
  252. data/spec/mongo/operation/write/insert_spec.rb +244 -0
  253. data/spec/mongo/operation/write/remove_user_spec.rb +46 -0
  254. data/spec/mongo/operation/write/response_spec.rb +85 -0
  255. data/spec/mongo/operation/write/update_spec.rb +228 -0
  256. data/spec/mongo/protocol/delete_spec.rb +167 -0
  257. data/spec/mongo/protocol/get_more_spec.rb +146 -0
  258. data/spec/mongo/protocol/insert_spec.rb +161 -0
  259. data/spec/mongo/protocol/kill_cursors_spec.rb +101 -0
  260. data/spec/mongo/protocol/query_spec.rb +285 -0
  261. data/spec/mongo/protocol/reply_spec.rb +157 -0
  262. data/spec/mongo/protocol/update_spec.rb +186 -0
  263. data/spec/mongo/server/connection_pool/queue_spec.rb +170 -0
  264. data/spec/mongo/server/connection_pool_spec.rb +120 -0
  265. data/spec/mongo/server/connection_spec.rb +312 -0
  266. data/spec/mongo/server/description/features_spec.rb +138 -0
  267. data/spec/mongo/server/description/inspector/primary_elected_spec.rb +94 -0
  268. data/spec/mongo/server/description/inspector/server_added_spec.rb +92 -0
  269. data/spec/mongo/server/description/inspector/server_removed_spec.rb +95 -0
  270. data/spec/mongo/server/description_spec.rb +510 -0
  271. data/spec/mongo/server/monitor_spec.rb +144 -0
  272. data/spec/mongo/server_discovery_and_monitoring_spec.rb +103 -0
  273. data/spec/mongo/server_selection_rtt_spec.rb +104 -0
  274. data/spec/mongo/server_selection_spec.rb +89 -0
  275. data/spec/mongo/server_selector/nearest_spec.rb +250 -0
  276. data/spec/mongo/server_selector/primary_preferred_spec.rb +290 -0
  277. data/spec/mongo/server_selector/primary_spec.rb +114 -0
  278. data/spec/mongo/server_selector/secondary_preferred_spec.rb +252 -0
  279. data/spec/mongo/server_selector/secondary_spec.rb +196 -0
  280. data/spec/mongo/server_selector_spec.rb +101 -0
  281. data/spec/mongo/server_spec.rb +131 -0
  282. data/spec/mongo/uri_spec.rb +517 -0
  283. data/spec/mongo/write_concern/acknowledged_spec.rb +44 -0
  284. data/spec/mongo/write_concern/unacknowledged_spec.rb +15 -0
  285. data/spec/spec_helper.rb +133 -0
  286. data/spec/support/authorization.rb +247 -0
  287. data/spec/support/crud/read.rb +144 -0
  288. data/spec/support/crud/write.rb +214 -0
  289. data/spec/support/crud.rb +203 -0
  290. data/spec/support/crud_tests/read/aggregate.yml +43 -0
  291. data/spec/support/crud_tests/read/count.yml +37 -0
  292. data/spec/support/crud_tests/read/distinct.yml +33 -0
  293. data/spec/support/crud_tests/read/find.yml +50 -0
  294. data/spec/support/crud_tests/write/deleteMany.yml +36 -0
  295. data/spec/support/crud_tests/write/deleteOne.yml +49 -0
  296. data/spec/support/crud_tests/write/findOneAndDelete.yml +54 -0
  297. data/spec/support/crud_tests/write/findOneAndReplace.yml +153 -0
  298. data/spec/support/crud_tests/write/findOneAndUpdate.yml +161 -0
  299. data/spec/support/crud_tests/write/insertMany.yml +24 -0
  300. data/spec/support/crud_tests/write/insertOne.yml +19 -0
  301. data/spec/support/crud_tests/write/replaceOne.yml +96 -0
  302. data/spec/support/crud_tests/write/updateMany.yml +83 -0
  303. data/spec/support/crud_tests/write/updateOne.yml +80 -0
  304. data/spec/support/helpers.rb +140 -0
  305. data/spec/support/matchers.rb +37 -0
  306. data/spec/support/sdam/rs/discover_arbiters.yml +41 -0
  307. data/spec/support/sdam/rs/discover_passives.yml +41 -0
  308. data/spec/support/sdam/rs/discover_primary.yml +40 -0
  309. data/spec/support/sdam/rs/discover_secondary.yml +41 -0
  310. data/spec/support/sdam/rs/discovery.yml +195 -0
  311. data/spec/support/sdam/rs/ghost_discovered.yml +39 -0
  312. data/spec/support/sdam/rs/hosts_differ_from_seeds.yml +34 -0
  313. data/spec/support/sdam/rs/member_reconfig.yml +68 -0
  314. data/spec/support/sdam/rs/member_standalone.yml +60 -0
  315. data/spec/support/sdam/rs/new_primary.yml +74 -0
  316. data/spec/support/sdam/rs/new_primary_wrong_set_name.yml +71 -0
  317. data/spec/support/sdam/rs/non_rs_member.yml +31 -0
  318. data/spec/support/sdam/rs/normalize_case.yml +49 -0
  319. data/spec/support/sdam/rs/primary_becomes_standalone.yml +52 -0
  320. data/spec/support/sdam/rs/primary_changes_set_name.yml +57 -0
  321. data/spec/support/sdam/rs/primary_disconnect.yml +56 -0
  322. data/spec/support/sdam/rs/primary_wrong_set_name.yml +27 -0
  323. data/spec/support/sdam/rs/response_from_removed.yml +63 -0
  324. data/spec/support/sdam/rs/rsother_discovered.yml +41 -0
  325. data/spec/support/sdam/rs/sec_not_auth.yml +49 -0
  326. data/spec/support/sdam/rs/secondary_wrong_set_name.yml +28 -0
  327. data/spec/support/sdam/rs/secondary_wrong_set_name_with_primary.yml +69 -0
  328. data/spec/support/sdam/rs/unexpected_mongos.yml +26 -0
  329. data/spec/support/sdam/rs/wrong_set_name.yml +35 -0
  330. data/spec/support/sdam/sharded/multiple_mongoses.yml +46 -0
  331. data/spec/support/sdam/sharded/non_mongos_removed.yml +41 -0
  332. data/spec/support/sdam/sharded/normalize_uri_case.yml +32 -0
  333. data/spec/support/sdam/single/direct_connection_external_ip.yml +34 -0
  334. data/spec/support/sdam/single/direct_connection_mongos.yml +33 -0
  335. data/spec/support/sdam/single/direct_connection_rsarbiter.yml +35 -0
  336. data/spec/support/sdam/single/direct_connection_rsprimary.yml +34 -0
  337. data/spec/support/sdam/single/direct_connection_rssecondary.yml +35 -0
  338. data/spec/support/sdam/single/direct_connection_slave.yml +32 -0
  339. data/spec/support/sdam/single/direct_connection_standalone.yml +32 -0
  340. data/spec/support/sdam/single/not_ok_response.yml +39 -0
  341. data/spec/support/sdam/single/standalone_removed.yml +32 -0
  342. data/spec/support/sdam/single/unavailable_seed.yml +28 -0
  343. data/spec/support/server_discovery_and_monitoring.rb +167 -0
  344. data/spec/support/server_selection/rtt/first_value.yml +4 -0
  345. data/spec/support/server_selection/rtt/first_value_zero.yml +4 -0
  346. data/spec/support/server_selection/rtt/value_test_1.yml +4 -0
  347. data/spec/support/server_selection/rtt/value_test_2.yml +4 -0
  348. data/spec/support/server_selection/rtt/value_test_3.yml +4 -0
  349. data/spec/support/server_selection/rtt/value_test_4.yml +4 -0
  350. data/spec/support/server_selection/rtt/value_test_5.yml +4 -0
  351. data/spec/support/server_selection/selection/ReplicaSetNoPrimary/read/Nearest.yml +26 -0
  352. data/spec/support/server_selection/selection/ReplicaSetNoPrimary/read/Nearest_non_matching.yml +21 -0
  353. data/spec/support/server_selection/selection/ReplicaSetNoPrimary/read/Primary.yml +21 -0
  354. data/spec/support/server_selection/selection/ReplicaSetNoPrimary/read/PrimaryPreferred.yml +26 -0
  355. data/spec/support/server_selection/selection/ReplicaSetNoPrimary/read/PrimaryPreferred_non_matching.yml +21 -0
  356. data/spec/support/server_selection/selection/ReplicaSetNoPrimary/read/Secondary.yml +26 -0
  357. data/spec/support/server_selection/selection/ReplicaSetNoPrimary/read/SecondaryPreferred.yml +26 -0
  358. data/spec/support/server_selection/selection/ReplicaSetNoPrimary/read/SecondaryPreferred_non_matching.yml +21 -0
  359. data/spec/support/server_selection/selection/ReplicaSetNoPrimary/read/Secondary_non_matching.yml +21 -0
  360. data/spec/support/server_selection/selection/ReplicaSetWithPrimary/read/Nearest.yml +33 -0
  361. data/spec/support/server_selection/selection/ReplicaSetWithPrimary/read/Nearest_non_matching.yml +26 -0
  362. data/spec/support/server_selection/selection/ReplicaSetWithPrimary/read/Primary.yml +29 -0
  363. data/spec/support/server_selection/selection/ReplicaSetWithPrimary/read/PrimaryPreferred.yml +29 -0
  364. data/spec/support/server_selection/selection/ReplicaSetWithPrimary/read/PrimaryPreferred_non_matching.yml +29 -0
  365. data/spec/support/server_selection/selection/ReplicaSetWithPrimary/read/Secondary.yml +31 -0
  366. data/spec/support/server_selection/selection/ReplicaSetWithPrimary/read/SecondaryPreferred.yml +31 -0
  367. data/spec/support/server_selection/selection/ReplicaSetWithPrimary/read/SecondaryPreferred_non_matching.yml +29 -0
  368. data/spec/support/server_selection/selection/ReplicaSetWithPrimary/read/Secondary_non_matching.yml +26 -0
  369. data/spec/support/server_selection/selection/Sharded/read/SecondaryPreferred.yml +26 -0
  370. data/spec/support/server_selection/selection/Single/read/SecondaryPreferred.yml +19 -0
  371. data/spec/support/server_selection/selection/Unknown/read/SecondaryPreferred.yml +11 -0
  372. data/spec/support/server_selection.rb +157 -0
  373. data/spec/support/server_selection_rtt.rb +41 -0
  374. data/spec/support/shared/bulk_write.rb +535 -0
  375. data/spec/support/shared/cursor.rb +38 -0
  376. data/spec/support/shared/operation.rb +77 -0
  377. data/spec/support/shared/protocol.rb +31 -0
  378. data/spec/support/shared/server_selector.rb +111 -0
  379. data/spec/support/shared/socket.rb +82 -0
  380. data/spec/support/travis.rb +14 -0
  381. data.tar.gz.sig +2 -3
  382. metadata +583 -186
  383. metadata.gz.sig +0 -0
  384. data/VERSION +0 -1
  385. data/lib/mongo/bulk_write_collection_view.rb +0 -387
  386. data/lib/mongo/collection_writer.rb +0 -364
  387. data/lib/mongo/connection/node.rb +0 -249
  388. data/lib/mongo/connection/pool.rb +0 -340
  389. data/lib/mongo/connection/pool_manager.rb +0 -320
  390. data/lib/mongo/connection/sharding_pool_manager.rb +0 -67
  391. data/lib/mongo/connection/socket/ssl_socket.rb +0 -95
  392. data/lib/mongo/connection/socket/tcp_socket.rb +0 -87
  393. data/lib/mongo/connection/socket/unix_socket.rb +0 -39
  394. data/lib/mongo/db.rb +0 -808
  395. data/lib/mongo/exception.rb +0 -145
  396. data/lib/mongo/functional/authentication.rb +0 -455
  397. data/lib/mongo/functional/logging.rb +0 -85
  398. data/lib/mongo/functional/read_preference.rb +0 -183
  399. data/lib/mongo/functional/scram.rb +0 -556
  400. data/lib/mongo/functional/uri_parser.rb +0 -409
  401. data/lib/mongo/functional/write_concern.rb +0 -66
  402. data/lib/mongo/gridfs/grid.rb +0 -112
  403. data/lib/mongo/gridfs/grid_ext.rb +0 -53
  404. data/lib/mongo/gridfs/grid_file_system.rb +0 -163
  405. data/lib/mongo/gridfs/grid_io.rb +0 -484
  406. data/lib/mongo/legacy.rb +0 -140
  407. data/lib/mongo/mongo_client.rb +0 -697
  408. data/lib/mongo/mongo_replica_set_client.rb +0 -535
  409. data/lib/mongo/mongo_sharded_client.rb +0 -159
  410. data/lib/mongo/networking.rb +0 -372
  411. data/lib/mongo/utils/conversions.rb +0 -110
  412. data/lib/mongo/utils/core_ext.rb +0 -70
  413. data/lib/mongo/utils/server_version.rb +0 -69
  414. data/lib/mongo/utils/support.rb +0 -80
  415. data/test/functional/authentication_test.rb +0 -39
  416. data/test/functional/bulk_api_stress_test.rb +0 -133
  417. data/test/functional/bulk_write_collection_view_test.rb +0 -1198
  418. data/test/functional/client_test.rb +0 -627
  419. data/test/functional/collection_test.rb +0 -2175
  420. data/test/functional/collection_writer_test.rb +0 -83
  421. data/test/functional/conversions_test.rb +0 -163
  422. data/test/functional/cursor_fail_test.rb +0 -57
  423. data/test/functional/cursor_message_test.rb +0 -56
  424. data/test/functional/cursor_test.rb +0 -683
  425. data/test/functional/db_api_test.rb +0 -835
  426. data/test/functional/db_test.rb +0 -348
  427. data/test/functional/grid_file_system_test.rb +0 -285
  428. data/test/functional/grid_io_test.rb +0 -252
  429. data/test/functional/grid_test.rb +0 -273
  430. data/test/functional/pool_test.rb +0 -136
  431. data/test/functional/safe_test.rb +0 -98
  432. data/test/functional/support_test.rb +0 -62
  433. data/test/functional/timeout_test.rb +0 -60
  434. data/test/functional/uri_test.rb +0 -446
  435. data/test/functional/write_concern_test.rb +0 -118
  436. data/test/helpers/general.rb +0 -50
  437. data/test/helpers/test_unit.rb +0 -476
  438. data/test/replica_set/authentication_test.rb +0 -37
  439. data/test/replica_set/basic_test.rb +0 -189
  440. data/test/replica_set/client_test.rb +0 -393
  441. data/test/replica_set/connection_test.rb +0 -138
  442. data/test/replica_set/count_test.rb +0 -66
  443. data/test/replica_set/cursor_test.rb +0 -220
  444. data/test/replica_set/insert_test.rb +0 -157
  445. data/test/replica_set/max_values_test.rb +0 -151
  446. data/test/replica_set/pinning_test.rb +0 -105
  447. data/test/replica_set/query_test.rb +0 -73
  448. data/test/replica_set/read_preference_test.rb +0 -219
  449. data/test/replica_set/refresh_test.rb +0 -211
  450. data/test/replica_set/replication_ack_test.rb +0 -95
  451. data/test/sharded_cluster/basic_test.rb +0 -203
  452. data/test/shared/authentication/basic_auth_shared.rb +0 -260
  453. data/test/shared/authentication/bulk_api_auth_shared.rb +0 -249
  454. data/test/shared/authentication/gssapi_shared.rb +0 -176
  455. data/test/shared/authentication/sasl_plain_shared.rb +0 -96
  456. data/test/shared/authentication/scram_shared.rb +0 -92
  457. data/test/shared/ssl_shared.rb +0 -235
  458. data/test/test_helper.rb +0 -61
  459. data/test/threading/basic_test.rb +0 -120
  460. data/test/tools/mongo_config.rb +0 -708
  461. data/test/tools/mongo_config_test.rb +0 -160
  462. data/test/unit/client_test.rb +0 -381
  463. data/test/unit/collection_test.rb +0 -166
  464. data/test/unit/connection_test.rb +0 -335
  465. data/test/unit/cursor_test.rb +0 -307
  466. data/test/unit/db_test.rb +0 -136
  467. data/test/unit/grid_test.rb +0 -76
  468. data/test/unit/mongo_sharded_client_test.rb +0 -48
  469. data/test/unit/node_test.rb +0 -93
  470. data/test/unit/pool_manager_test.rb +0 -111
  471. data/test/unit/read_pref_test.rb +0 -406
  472. data/test/unit/read_test.rb +0 -159
  473. data/test/unit/safe_test.rb +0 -158
  474. data/test/unit/sharding_pool_manager_test.rb +0 -84
  475. data/test/unit/write_concern_test.rb +0 -175
@@ -1,163 +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 file store built on the GridFS specification featuring
18
- # an API and behavior similar to that of a traditional file system.
19
- class GridFileSystem
20
- include GridExt::InstanceMethods
21
-
22
- # Initialize a new GridFileSystem instance, consisting of a MongoDB database
23
- # and a filesystem prefix if not using the default.
24
- #
25
- # @param [Mongo::DB] db a MongoDB database.
26
- # @param [String] fs_name A name for the file system. The default name, based on
27
- # the specification, is 'fs'.
28
- def initialize(db, fs_name=Grid::DEFAULT_FS_NAME)
29
- raise MongoArgumentError, "db must be a Mongo::DB." unless db.is_a?(Mongo::DB)
30
-
31
- @db = db
32
- @files = @db["#{fs_name}.files"]
33
- @chunks = @db["#{fs_name}.chunks"]
34
- @fs_name = fs_name
35
-
36
- @default_query_opts = {:sort => [['filename', 1], ['uploadDate', -1]], :limit => 1}
37
-
38
- # This will create indexes only if we're connected to a primary node.
39
- begin
40
- @files.ensure_index([['filename', 1], ['uploadDate', -1]])
41
- @chunks.ensure_index([['files_id', Mongo::ASCENDING], ['n', Mongo::ASCENDING]], :unique => true)
42
- rescue Mongo::ConnectionFailure
43
- end
44
- end
45
-
46
- # Open a file for reading or writing. Note that the options for this method only apply
47
- # when opening in 'w' mode.
48
- #
49
- # Note that arbitrary metadata attributes can be saved to the file by passing
50
- # them is as options.
51
- #
52
- # @param [String] filename the name of the file.
53
- # @param [String] mode either 'r' or 'w' for reading from
54
- # or writing to the file.
55
- # @param [Hash] opts see GridIO#new
56
- #
57
- # @option opts [Hash] :metadata ({}) any additional data to store with the file.
58
- # @option opts [ObjectId] :_id (ObjectId) a unique id for
59
- # the file to be use in lieu of an automatically generated one.
60
- # @option opts [String] :content_type ('binary/octet-stream') If no content type is specified,
61
- # the content type will may be inferred from the filename extension if the mime-types gem can be
62
- # loaded. Otherwise, the content type 'binary/octet-stream' will be used.
63
- # @option opts [Integer] (261120) :chunk_size size of file chunks in bytes.
64
- # @option opts [Boolean] :delete_old (false) ensure that old versions of the file are deleted. This option
65
- # only work in 'w' mode. Certain precautions must be taken when deleting GridFS files. See the notes under
66
- # GridFileSystem#delete.
67
- # @option opts [String, Integer, Symbol] :w (1) Set write concern
68
- #
69
- # Notes on write concern:
70
- # When :w > 0, the chunks sent to the server
71
- # will be validated using an md5 hash. If validation fails, an exception will be raised.
72
- # @option opts [Integer] :versions (false) deletes all versions which exceed the number specified to
73
- # retain ordered by uploadDate. This option only works in 'w' mode. Certain precautions must be taken when
74
- # deleting GridFS files. See the notes under GridFileSystem#delete.
75
- #
76
- # @example
77
- #
78
- # # Store the text "Hello, world!" in the grid file system.
79
- # @grid = Mongo::GridFileSystem.new(@db)
80
- # @grid.open('filename', 'w') do |f|
81
- # f.write "Hello, world!"
82
- # end
83
- #
84
- # # Output "Hello, world!"
85
- # @grid = Mongo::GridFileSystem.new(@db)
86
- # @grid.open('filename', 'r') do |f|
87
- # puts f.read
88
- # end
89
- #
90
- # # Write a file on disk to the GridFileSystem
91
- # @file = File.open('image.jpg')
92
- # @grid = Mongo::GridFileSystem.new(@db)
93
- # @grid.open('image.jpg, 'w') do |f|
94
- # f.write @file
95
- # end
96
- #
97
- # @return [Mongo::GridIO]
98
- def open(filename, mode, opts={})
99
- opts = opts.dup
100
- opts.merge!(default_grid_io_opts(filename))
101
- if mode == 'w'
102
- begin
103
- # Ensure there are the appropriate indexes, as state may have changed since instantiation of self.
104
- # Recall that index definitions are cached with ensure_index so this statement won't unneccesarily repeat index creation.
105
- @files.ensure_index([['filename', 1], ['uploadDate', -1]])
106
- @chunks.ensure_index([['files_id', Mongo::ASCENDING], ['n', Mongo::ASCENDING]], :unique => true)
107
- versions = opts.delete(:versions)
108
- if opts.delete(:delete_old) || (versions && versions < 1)
109
- versions = 1
110
- end
111
- rescue Mongo::ConnectionFailure => e
112
- raise e, "Failed to create necessary indexes and write data."
113
- return
114
- end
115
- end
116
- file = GridIO.new(@files, @chunks, filename, mode, opts)
117
- return file unless block_given?
118
- result = nil
119
- begin
120
- result = yield file
121
- ensure
122
- id = file.close
123
- if versions
124
- self.delete do
125
- @files.find({'filename' => filename, '_id' => {'$ne' => id}}, :fields => ['_id'], :sort => ['uploadDate', -1], :skip => (versions - 1))
126
- end
127
- end
128
- end
129
- result
130
- end
131
-
132
- # Delete the file with the given filename. Note that this will delete
133
- # all versions of the file.
134
- #
135
- # Be careful with this. Deleting a GridFS file can result in read errors if another process
136
- # is attempting to read a file while it's being deleted. While the odds for this
137
- # kind of race condition are small, it's important to be aware of.
138
- #
139
- # @param [String] filename
140
- #
141
- # @yield [] pass a block that returns an array of documents to be deleted.
142
- #
143
- # @return [Boolean]
144
- def delete(filename=nil)
145
- if block_given?
146
- files = yield
147
- else
148
- files = @files.find({'filename' => filename}, :fields => ['_id'])
149
- end
150
- files.each do |file|
151
- @files.remove({'_id' => file['_id']})
152
- @chunks.remove({'files_id' => file['_id']})
153
- end
154
- end
155
- alias_method :unlink, :delete
156
-
157
- private
158
-
159
- def default_grid_io_opts(filename=nil)
160
- {:fs_name => @fs_name, :query => {'filename' => filename}, :query_opts => @default_query_opts}
161
- end
162
- end
163
- end
@@ -1,484 +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
- require 'digest/md5'
16
-
17
- module Mongo
18
-
19
- # GridIO objects represent files in the GridFS specification. This class
20
- # manages the reading and writing of file chunks and metadata.
21
- class GridIO
22
- include Mongo::WriteConcern
23
-
24
- DEFAULT_CHUNK_SIZE = 255 * 1024
25
- DEFAULT_CONTENT_TYPE = 'binary/octet-stream'
26
- PROTECTED_ATTRS = [:files_id, :file_length, :client_md5, :server_md5]
27
-
28
- attr_reader :content_type, :chunk_size, :upload_date, :files_id, :filename,
29
- :metadata, :server_md5, :client_md5, :file_length, :file_position
30
-
31
- # Create a new GridIO object. Note that most users will not need to use this class directly;
32
- # the Grid and GridFileSystem classes will instantiate this class
33
- #
34
- # @param [Mongo::Collection] files a collection for storing file metadata.
35
- # @param [Mongo::Collection] chunks a collection for storing file chunks.
36
- # @param [String] filename the name of the file to open or write.
37
- # @param [String] mode 'r' or 'w' or reading or creating a file.
38
- #
39
- # @option opts [Hash] :query a query selector used when opening the file in 'r' mode.
40
- # @option opts [Hash] :query_opts any query options to be used when opening the file in 'r' mode.
41
- # @option opts [String] :fs_name the file system prefix.
42
- # @option opts [Integer] (261120) :chunk_size size of file chunks in bytes.
43
- # @option opts [Hash] :metadata ({}) any additional data to store with the file.
44
- # @option opts [ObjectId] :_id (ObjectId) a unique id for
45
- # the file to be use in lieu of an automatically generated one.
46
- # @option opts [String] :content_type ('binary/octet-stream') If no content type is specified,
47
- # the content type will may be inferred from the filename extension if the mime-types gem can be
48
- # loaded. Otherwise, the content type 'binary/octet-stream' will be used.
49
- # @option opts [String, Integer, Symbol] :w (1) Set the write concern
50
- #
51
- # Notes on write concern:
52
- # When :w > 0, the chunks sent to the server
53
- # will be validated using an md5 hash. If validation fails, an exception will be raised.
54
- def initialize(files, chunks, filename, mode, opts={})
55
- @files = files
56
- @chunks = chunks
57
- @filename = filename
58
- @mode = mode
59
- opts = opts.dup
60
- @query = opts.delete(:query) || {}
61
- @query_opts = opts.delete(:query_opts) || {}
62
- @fs_name = opts.delete(:fs_name) || Grid::DEFAULT_FS_NAME
63
- @write_concern = get_write_concern(opts)
64
- @local_md5 = Digest::MD5.new if Mongo::WriteConcern.gle?(@write_concern)
65
- @custom_attrs = {}
66
-
67
- case @mode
68
- when 'r' then init_read
69
- when 'w' then init_write(opts)
70
- else
71
- raise GridError, "Invalid file mode #{@mode}. Mode should be 'r' or 'w'."
72
- end
73
- end
74
-
75
- def [](key)
76
- @custom_attrs[key] || instance_variable_get("@#{key.to_s}")
77
- end
78
-
79
- def []=(key, value)
80
- if PROTECTED_ATTRS.include?(key.to_sym)
81
- warn "Attempting to overwrite protected value."
82
- return nil
83
- else
84
- @custom_attrs[key] = value
85
- end
86
- end
87
-
88
- # Read the data from the file. If a length if specified, will read from the
89
- # current file position.
90
- #
91
- # @param [Integer] length
92
- #
93
- # @return [String]
94
- # the data in the file
95
- def read(length=nil)
96
- return '' if @file_length.zero?
97
- if length == 0
98
- return ''
99
- elsif length.nil? && @file_position.zero?
100
- read_all
101
- else
102
- read_length(length)
103
- end
104
- end
105
- alias_method :data, :read
106
-
107
- # Write the given string (binary) data to the file.
108
- #
109
- # @param [String] io the data to write.
110
- #
111
- # @return [Integer] the number of bytes written.
112
- def write(io)
113
- raise GridError, "file not opened for write" unless @mode[0] == ?w
114
- if io.is_a? String
115
- if Mongo::WriteConcern.gle?(@write_concern)
116
- @local_md5.update(io)
117
- end
118
- write_string(io)
119
- else
120
- length = 0
121
- if Mongo::WriteConcern.gle?(@write_concern)
122
- while(string = io.read(@chunk_size))
123
- @local_md5.update(string)
124
- length += write_string(string)
125
- end
126
- else
127
- while(string = io.read(@chunk_size))
128
- length += write_string(string)
129
- end
130
- end
131
- length
132
- end
133
- end
134
-
135
- # Position the file pointer at the provided location.
136
- #
137
- # @param [Integer] pos
138
- # the number of bytes to advance the file pointer. this can be a negative
139
- # number.
140
- # @param [Integer] whence
141
- # one of IO::SEEK_CUR, IO::SEEK_END, or IO::SEEK_SET
142
- #
143
- # @return [Integer] the new file position
144
- def seek(pos, whence=IO::SEEK_SET)
145
- raise GridError, "Seek is only allowed in read mode." unless @mode == 'r'
146
- target_pos = case whence
147
- when IO::SEEK_CUR
148
- @file_position + pos
149
- when IO::SEEK_END
150
- @file_length + pos
151
- when IO::SEEK_SET
152
- pos
153
- end
154
-
155
- new_chunk_number = (target_pos / @chunk_size).to_i
156
- if new_chunk_number != @current_chunk['n']
157
- save_chunk(@current_chunk) if @mode[0] == ?w
158
- @current_chunk = get_chunk(new_chunk_number)
159
- end
160
- @file_position = target_pos
161
- @chunk_position = @file_position % @chunk_size
162
- @file_position
163
- end
164
-
165
- # The current position of the file.
166
- #
167
- # @return [Integer]
168
- def tell
169
- @file_position
170
- end
171
- alias :pos :tell
172
-
173
- # Rewind the file. This is equivalent to seeking to the zeroth position.
174
- #
175
- # @return [Integer] the position of the file after rewinding (always zero).
176
- def rewind
177
- raise GridError, "file not opened for read" unless @mode[0] == ?r
178
- seek(0)
179
- end
180
-
181
- # Return a boolean indicating whether the position pointer is
182
- # at the end of the file.
183
- #
184
- # @return [Boolean]
185
- def eof
186
- raise GridError, "file not opened for read #{@mode}" unless @mode[0] == ?r
187
- @file_position >= @file_length
188
- end
189
- alias :eof? :eof
190
-
191
- # Return the next line from a GridFS file. This probably
192
- # makes sense only if you're storing plain text. This method
193
- # has a somewhat tricky API, which it inherits from Ruby's
194
- # StringIO#gets.
195
- #
196
- # @param [String, Integer] separator or length. If a separator,
197
- # read up to the separator. If a length, read the +length+ number
198
- # of bytes. If nil, read the entire file.
199
- # @param [Integer] length If a separator is provided, then
200
- # read until either finding the separator or
201
- # passing over the +length+ number of bytes.
202
- #
203
- # @return [String]
204
- def gets(separator="\n", length=nil)
205
- if separator.nil?
206
- read_all
207
- elsif separator.is_a?(Integer)
208
- read_length(separator)
209
- elsif separator.length > 1
210
- read_to_string(separator, length)
211
- else
212
- read_to_character(separator, length)
213
- end
214
- end
215
-
216
- # Return the next byte from the GridFS file.
217
- #
218
- # @return [String]
219
- def getc
220
- read_length(1)
221
- end
222
-
223
- # Creates or updates the document from the files collection that
224
- # stores the chunks' metadata. The file becomes available only after
225
- # this method has been called.
226
- #
227
- # This method will be invoked automatically when
228
- # on GridIO#open is passed a block. Otherwise, it must be called manually.
229
- #
230
- # @return [BSON::ObjectId]
231
- def close
232
- if @mode[0] == ?w
233
- if @current_chunk['n'].zero? && @chunk_position.zero?
234
- warn "Warning: Storing a file with zero length."
235
- end
236
- @upload_date = Time.now.utc
237
- id = @files.insert(to_mongo_object)
238
- end
239
- id
240
- end
241
-
242
- # Read a chunk of the data from the file and yield it to the given
243
- # block.
244
- #
245
- # Note that this method reads from the current file position.
246
- #
247
- # @yield Yields on chunk per iteration as defined by this file's
248
- # chunk size.
249
- #
250
- # @return [Mongo::GridIO] self
251
- def each
252
- return read_all unless block_given?
253
- while chunk = read(chunk_size)
254
- yield chunk
255
- break if chunk.empty?
256
- end
257
- self
258
- end
259
-
260
- def inspect
261
- "#<GridIO _id: #{@files_id}>"
262
- end
263
-
264
- private
265
-
266
- def create_chunk(n)
267
- chunk = BSON::OrderedHash.new
268
- chunk['_id'] = BSON::ObjectId.new
269
- chunk['n'] = n
270
- chunk['files_id'] = @files_id
271
- chunk['data'] = ''
272
- @chunk_position = 0
273
- chunk
274
- end
275
-
276
- def save_chunk(chunk)
277
- @chunks.save(chunk)
278
- end
279
-
280
- def get_chunk(n)
281
- chunk = @chunks.find({'files_id' => @files_id, 'n' => n}).next_document
282
- @chunk_position = 0
283
- chunk
284
- end
285
-
286
- # Read a file in its entirety.
287
- def read_all
288
- buf = ''
289
- if @current_chunk
290
- buf << @current_chunk['data'].to_s
291
- while buf.size < @file_length
292
- @current_chunk = get_chunk(@current_chunk['n'] + 1)
293
- break if @current_chunk.nil?
294
- buf << @current_chunk['data'].to_s
295
- end
296
- @file_position = @file_length
297
- end
298
- buf
299
- end
300
-
301
- # Read a file incrementally.
302
- def read_length(length)
303
- cache_chunk_data
304
- remaining = (@file_length - @file_position)
305
- if length.nil?
306
- to_read = remaining
307
- else
308
- to_read = length > remaining ? remaining : length
309
- end
310
- return nil unless remaining > 0
311
-
312
- buf = ''
313
- while to_read > 0
314
- if @chunk_position == @chunk_data_length
315
- @current_chunk = get_chunk(@current_chunk['n'] + 1)
316
- cache_chunk_data
317
- end
318
- chunk_remainder = @chunk_data_length - @chunk_position
319
- size = (to_read >= chunk_remainder) ? chunk_remainder : to_read
320
- buf << @current_chunk_data[@chunk_position, size]
321
- to_read -= size
322
- @chunk_position += size
323
- @file_position += size
324
- end
325
- buf
326
- end
327
-
328
- def read_to_character(character="\n", length=nil)
329
- result = ''
330
- len = 0
331
- while char = getc
332
- result << char
333
- len += 1
334
- break if char == character || (length ? len >= length : false)
335
- end
336
- result.length > 0 ? result : nil
337
- end
338
-
339
- def read_to_string(string="\n", length=nil)
340
- result = ''
341
- len = 0
342
- match_idx = 0
343
- match_num = string.length - 1
344
- to_match = string[match_idx].chr
345
- if length
346
- matcher = lambda {|idx, num| idx < num && len < length }
347
- else
348
- matcher = lambda {|idx, num| idx < num}
349
- end
350
- while matcher.call(match_idx, match_num) && char = getc
351
- result << char
352
- len += 1
353
- if char == to_match
354
- while match_idx < match_num do
355
- match_idx += 1
356
- to_match = string[match_idx].chr
357
- char = getc
358
- result << char
359
- if char != to_match
360
- match_idx = 0
361
- to_match = string[match_idx].chr
362
- break
363
- end
364
- end
365
- end
366
- end
367
- result.length > 0 ? result : nil
368
- end
369
-
370
- def cache_chunk_data
371
- @current_chunk_data = @current_chunk['data'].to_s
372
- if @current_chunk_data.respond_to?(:force_encoding)
373
- @current_chunk_data.force_encoding("binary")
374
- end
375
- @chunk_data_length = @current_chunk['data'].length
376
- end
377
-
378
- def write_string(string)
379
- # Since Ruby 1.9.1 doesn't necessarily store one character per byte.
380
- if string.respond_to?(:force_encoding)
381
- string.force_encoding("binary")
382
- end
383
-
384
- to_write = string.length
385
- while (to_write > 0) do
386
- if @current_chunk && @chunk_position == @chunk_size
387
- next_chunk_number = @current_chunk['n'] + 1
388
- @current_chunk = create_chunk(next_chunk_number)
389
- end
390
- chunk_available = @chunk_size - @chunk_position
391
- step_size = (to_write > chunk_available) ? chunk_available : to_write
392
- @current_chunk['data'] = BSON::Binary.new((@current_chunk['data'].to_s << string[-to_write, step_size]).unpack("c*"))
393
- @chunk_position += step_size
394
- to_write -= step_size
395
- save_chunk(@current_chunk)
396
- end
397
- string.length - to_write
398
- end
399
-
400
- # Initialize the class for reading a file.
401
- def init_read
402
- doc = @files.find(@query, @query_opts).next_document
403
- raise GridFileNotFound, "Could not open file matching #{@query.inspect} #{@query_opts.inspect}" unless doc
404
-
405
- @files_id = doc['_id']
406
- @content_type = doc['contentType']
407
- @chunk_size = doc['chunkSize']
408
- @upload_date = doc['uploadDate']
409
- @aliases = doc['aliases']
410
- @file_length = doc['length']
411
- @metadata = doc['metadata']
412
- @md5 = doc['md5']
413
- @filename = doc['filename']
414
- @custom_attrs = doc
415
-
416
- @current_chunk = get_chunk(0)
417
- @file_position = 0
418
- end
419
-
420
- # Initialize the class for writing a file.
421
- def init_write(opts)
422
- opts = opts.dup
423
- @files_id = opts.delete(:_id) || BSON::ObjectId.new
424
- @content_type = opts.delete(:content_type) || (defined? MIME) && get_content_type || DEFAULT_CONTENT_TYPE
425
- @chunk_size = opts.delete(:chunk_size) || DEFAULT_CHUNK_SIZE
426
- @metadata = opts.delete(:metadata)
427
- @aliases = opts.delete(:aliases)
428
- @file_length = 0
429
- opts.each {|k, v| self[k] = v}
430
- check_existing_file if Mongo::WriteConcern.gle?(@write_concern)
431
-
432
- @current_chunk = create_chunk(0)
433
- @file_position = 0
434
- end
435
-
436
- def check_existing_file
437
- if @files.find_one('_id' => @files_id)
438
- raise GridError, "Attempting to overwrite with Grid#put. You must delete the file first."
439
- end
440
- end
441
-
442
- def to_mongo_object
443
- h = BSON::OrderedHash.new
444
- h['_id'] = @files_id
445
- h['filename'] = @filename if @filename
446
- h['contentType'] = @content_type
447
- h['length'] = @current_chunk ? @current_chunk['n'] * @chunk_size + @chunk_position : 0
448
- h['chunkSize'] = @chunk_size
449
- h['uploadDate'] = @upload_date
450
- h['aliases'] = @aliases if @aliases
451
- h['metadata'] = @metadata if @metadata
452
- h['md5'] = get_md5
453
- h.merge!(@custom_attrs)
454
- h
455
- end
456
-
457
- # Get a server-side md5 and validate against the client if running with acknowledged writes
458
- def get_md5
459
- md5_command = BSON::OrderedHash.new
460
- md5_command['filemd5'] = @files_id
461
- md5_command['root'] = @fs_name
462
- @server_md5 = @files.db.command(md5_command)['md5']
463
- if Mongo::WriteConcern.gle?(@write_concern)
464
- @client_md5 = @local_md5.hexdigest
465
- if @local_md5 == @server_md5
466
- @server_md5
467
- else
468
- raise GridMD5Failure, "File on server failed MD5 check"
469
- end
470
- else
471
- @server_md5
472
- end
473
- end
474
-
475
- # Determine the content type based on the filename.
476
- def get_content_type
477
- if @filename
478
- if types = MIME::Types.type_for(@filename)
479
- types.first.simplified unless types.empty?
480
- end
481
- end
482
- end
483
- end
484
- end