mongo 1.12.5 → 2.0.0.beta

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (437) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/CONTRIBUTING.md +64 -0
  5. data/LICENSE +1 -1
  6. data/README.md +23 -125
  7. data/Rakefile +26 -21
  8. data/bin/mongo_console +6 -38
  9. data/lib/mongo.rb +23 -82
  10. data/lib/mongo/address.rb +111 -0
  11. data/lib/mongo/address/ipv4.rb +85 -0
  12. data/lib/mongo/address/ipv6.rb +85 -0
  13. data/lib/mongo/address/unix.rb +76 -0
  14. data/lib/mongo/auth.rb +108 -0
  15. data/lib/mongo/auth/cr.rb +44 -0
  16. data/lib/mongo/auth/cr/conversation.rb +119 -0
  17. data/lib/mongo/auth/executable.rb +52 -0
  18. data/lib/mongo/auth/ldap.rb +48 -0
  19. data/lib/mongo/auth/ldap/conversation.rb +92 -0
  20. data/lib/mongo/auth/roles.rb +104 -0
  21. data/lib/mongo/auth/scram.rb +53 -0
  22. data/lib/mongo/auth/scram/conversation.rb +450 -0
  23. data/lib/mongo/auth/user.rb +159 -0
  24. data/lib/mongo/auth/user/view.rb +102 -0
  25. data/lib/mongo/auth/x509.rb +48 -0
  26. data/lib/mongo/auth/x509/conversation.rb +92 -0
  27. data/lib/mongo/{gridfs.rb → bulk.rb} +2 -5
  28. data/lib/mongo/bulk/bulk_write.rb +307 -0
  29. data/lib/mongo/client.rb +233 -0
  30. data/lib/mongo/cluster.rb +203 -0
  31. data/lib/mongo/cluster/topology.rb +60 -0
  32. data/lib/mongo/cluster/topology/replica_set.rb +160 -0
  33. data/lib/mongo/cluster/topology/sharded.rb +132 -0
  34. data/lib/mongo/cluster/topology/standalone.rb +132 -0
  35. data/lib/mongo/cluster/topology/unknown.rb +155 -0
  36. data/lib/mongo/collection.rb +130 -1101
  37. data/lib/mongo/collection/view.rb +169 -0
  38. data/lib/mongo/collection/view/aggregation.rb +108 -0
  39. data/lib/mongo/collection/view/explainable.rb +49 -0
  40. data/lib/mongo/collection/view/immutable.rb +43 -0
  41. data/lib/mongo/collection/view/iterable.rb +48 -0
  42. data/lib/mongo/collection/view/map_reduce.rb +191 -0
  43. data/lib/mongo/collection/view/readable.rb +363 -0
  44. data/lib/mongo/collection/view/writable.rb +169 -0
  45. data/lib/mongo/cursor.rb +79 -680
  46. data/lib/mongo/database.rb +224 -0
  47. data/lib/mongo/database/view.rb +101 -0
  48. data/lib/mongo/error.rb +81 -0
  49. data/lib/mongo/error/bulk_write_failure.rb +41 -0
  50. data/lib/mongo/{utils/thread_local_variable_manager.rb → error/empty_batch.rb} +22 -8
  51. data/{test/functional/db_connection_test.rb → lib/mongo/error/invalid_bulk_operation.rb} +19 -8
  52. data/lib/mongo/error/invalid_collection_name.rb +39 -0
  53. data/lib/mongo/error/invalid_database_name.rb +39 -0
  54. data/{test/replica_set/ssl_test.rb → lib/mongo/error/invalid_document.rb} +21 -14
  55. data/lib/mongo/error/invalid_file.rb +38 -0
  56. data/lib/mongo/error/invalid_nonce.rb +46 -0
  57. data/lib/mongo/error/invalid_replacement_document.rb +39 -0
  58. data/lib/mongo/error/invalid_signature.rb +47 -0
  59. data/{test/functional/ssl_test.rb → lib/mongo/error/invalid_update_document.rb} +22 -12
  60. data/lib/mongo/error/max_bson_size.rb +40 -0
  61. data/lib/mongo/error/max_message_size.rb +42 -0
  62. data/lib/mongo/{utils.rb → error/need_primary_server.rb} +10 -6
  63. data/lib/mongo/{connection.rb → error/operation_failure.rb} +10 -6
  64. data/lib/mongo/error/parser.rb +77 -0
  65. data/lib/mongo/{connection/socket.rb → error/socket_error.rb} +10 -5
  66. data/lib/mongo/error/socket_timeout_error.rb +23 -0
  67. data/lib/mongo/error/unsupported_features.rb +43 -0
  68. data/lib/mongo/event.rb +40 -0
  69. data/lib/mongo/event/listeners.rb +63 -0
  70. data/lib/mongo/event/primary_elected.rb +53 -0
  71. data/lib/mongo/event/publisher.rb +42 -0
  72. data/lib/mongo/event/server_added.rb +53 -0
  73. data/lib/mongo/event/server_removed.rb +53 -0
  74. data/lib/mongo/event/subscriber.rb +41 -0
  75. data/lib/mongo/grid.rb +16 -0
  76. data/lib/mongo/grid/file.rb +94 -0
  77. data/lib/mongo/grid/file/chunk.rb +184 -0
  78. data/lib/mongo/grid/file/metadata.rb +223 -0
  79. data/lib/mongo/grid/fs.rb +149 -0
  80. data/lib/mongo/index.rb +64 -0
  81. data/lib/mongo/index/view.rb +205 -0
  82. data/lib/mongo/loggable.rb +126 -0
  83. data/lib/mongo/logger.rb +132 -0
  84. data/lib/mongo/operation.rb +26 -0
  85. data/lib/mongo/operation/aggregate.rb +100 -0
  86. data/lib/mongo/operation/aggregate/result.rb +84 -0
  87. data/lib/mongo/operation/batchable.rb +103 -0
  88. data/lib/mongo/operation/bulk_delete/result.rb +197 -0
  89. data/lib/mongo/operation/bulk_insert/result.rb +195 -0
  90. data/lib/mongo/operation/bulk_update/result.rb +295 -0
  91. data/lib/mongo/operation/command.rb +62 -0
  92. data/lib/mongo/operation/executable.rb +105 -0
  93. data/lib/mongo/operation/kill_cursors.rb +39 -0
  94. data/lib/mongo/operation/limited.rb +37 -0
  95. data/lib/mongo/operation/list_collections/result.rb +116 -0
  96. data/lib/mongo/operation/list_indexes/result.rb +118 -0
  97. data/lib/mongo/operation/map_reduce.rb +96 -0
  98. data/lib/mongo/operation/map_reduce/result.rb +122 -0
  99. data/lib/mongo/{functional.rb → operation/read.rb} +7 -7
  100. data/lib/mongo/operation/read/collections_info.rb +67 -0
  101. data/lib/mongo/operation/read/get_more.rb +71 -0
  102. data/lib/mongo/operation/read/indexes.rb +68 -0
  103. data/lib/mongo/operation/read/list_collections.rb +75 -0
  104. data/lib/mongo/operation/read/list_indexes.rb +77 -0
  105. data/lib/mongo/operation/read/query.rb +71 -0
  106. data/lib/mongo/operation/read_preferrable.rb +34 -0
  107. data/lib/mongo/operation/result.rb +259 -0
  108. data/lib/mongo/operation/specifiable.rb +380 -0
  109. data/lib/mongo/operation/write.rb +25 -0
  110. data/lib/mongo/operation/write/bulk_delete.rb +158 -0
  111. data/lib/mongo/operation/write/bulk_insert.rb +160 -0
  112. data/lib/mongo/operation/write/bulk_update.rb +167 -0
  113. data/lib/mongo/{connection/socket/socket_util.rb → operation/write/command.rb} +9 -24
  114. data/lib/mongo/operation/write/command/create_user.rb +43 -0
  115. data/lib/mongo/operation/write/command/delete.rb +56 -0
  116. data/lib/mongo/operation/write/command/drop_index.rb +51 -0
  117. data/lib/mongo/operation/write/command/ensure_index.rb +55 -0
  118. data/lib/mongo/operation/write/command/insert.rb +55 -0
  119. data/lib/mongo/operation/write/command/remove_user.rb +42 -0
  120. data/lib/mongo/operation/write/command/update.rb +60 -0
  121. data/lib/mongo/operation/write/command/writable.rb +61 -0
  122. data/lib/mongo/operation/write/create_index.rb +84 -0
  123. data/lib/mongo/operation/write/create_user.rb +75 -0
  124. data/lib/mongo/operation/write/delete.rb +91 -0
  125. data/lib/mongo/operation/write/drop_index.rb +62 -0
  126. data/lib/mongo/operation/write/insert.rb +88 -0
  127. data/lib/mongo/operation/write/remove_user.rb +70 -0
  128. data/lib/mongo/operation/write/update.rb +98 -0
  129. data/lib/mongo/protocol.rb +15 -0
  130. data/lib/mongo/protocol/bit_vector.rb +61 -0
  131. data/lib/mongo/protocol/delete.rb +94 -0
  132. data/lib/mongo/protocol/get_more.rb +99 -0
  133. data/lib/mongo/protocol/insert.rb +99 -0
  134. data/lib/mongo/protocol/kill_cursors.rb +74 -0
  135. data/lib/mongo/protocol/message.rb +252 -0
  136. data/lib/mongo/protocol/query.rb +147 -0
  137. data/lib/mongo/protocol/reply.rb +72 -0
  138. data/lib/mongo/protocol/serializers.rb +180 -0
  139. data/lib/mongo/protocol/update.rb +111 -0
  140. data/lib/mongo/server.rb +163 -0
  141. data/lib/mongo/server/connectable.rb +99 -0
  142. data/lib/mongo/server/connection.rb +133 -0
  143. data/lib/mongo/server/connection_pool.rb +141 -0
  144. data/lib/mongo/server/connection_pool/queue.rb +182 -0
  145. data/lib/mongo/server/context.rb +66 -0
  146. data/lib/mongo/server/description.rb +450 -0
  147. data/lib/mongo/server/description/features.rb +85 -0
  148. data/lib/mongo/server/description/inspector.rb +79 -0
  149. data/lib/mongo/server/description/inspector/primary_elected.rb +58 -0
  150. data/lib/mongo/server/description/inspector/server_added.rb +59 -0
  151. data/lib/mongo/server/description/inspector/server_removed.rb +59 -0
  152. data/lib/mongo/server/monitor.rb +160 -0
  153. data/lib/mongo/server/monitor/connection.rb +88 -0
  154. data/lib/mongo/server_selector.rb +81 -0
  155. data/lib/mongo/server_selector/nearest.rb +94 -0
  156. data/lib/mongo/server_selector/primary.rb +88 -0
  157. data/lib/mongo/server_selector/primary_preferred.rb +94 -0
  158. data/lib/mongo/server_selector/secondary.rb +91 -0
  159. data/lib/mongo/server_selector/secondary_preferred.rb +96 -0
  160. data/lib/mongo/server_selector/selectable.rb +209 -0
  161. data/lib/mongo/socket.rb +179 -0
  162. data/lib/mongo/socket/ssl.rb +108 -0
  163. data/lib/mongo/socket/tcp.rb +69 -0
  164. data/lib/mongo/socket/unix.rb +66 -0
  165. data/lib/mongo/uri.rb +504 -0
  166. data/lib/mongo/version.rb +21 -0
  167. data/lib/mongo/write_concern.rb +99 -0
  168. data/lib/mongo/write_concern/acknowledged.rb +38 -0
  169. data/lib/mongo/write_concern/normalizable.rb +73 -0
  170. data/lib/mongo/write_concern/unacknowledged.rb +43 -0
  171. data/mongo.gemspec +17 -14
  172. data/spec/mongo/address/ipv4_spec.rb +74 -0
  173. data/spec/mongo/address/ipv6_spec.rb +74 -0
  174. data/spec/mongo/address/unix_spec.rb +30 -0
  175. data/spec/mongo/address_spec.rb +206 -0
  176. data/spec/mongo/auth/cr_spec.rb +59 -0
  177. data/spec/mongo/auth/ldap_spec.rb +40 -0
  178. data/spec/mongo/auth/scram/conversation_spec.rb +197 -0
  179. data/spec/mongo/auth/scram_spec.rb +55 -0
  180. data/spec/mongo/auth/user/view_spec.rb +76 -0
  181. data/spec/mongo/auth/user_spec.rb +190 -0
  182. data/spec/mongo/auth/x509_spec.rb +40 -0
  183. data/spec/mongo/auth_spec.rb +65 -0
  184. data/spec/mongo/bulk/bulk_write_spec.rb +175 -0
  185. data/spec/mongo/client_spec.rb +564 -0
  186. data/spec/mongo/cluster/topology/replica_set_spec.rb +101 -0
  187. data/spec/mongo/cluster/topology/sharded_spec.rb +74 -0
  188. data/spec/mongo/cluster/topology/standalone_spec.rb +79 -0
  189. data/spec/mongo/cluster/topology_spec.rb +65 -0
  190. data/spec/mongo/cluster_spec.rb +129 -0
  191. data/spec/mongo/collection/view/aggregation_spec.rb +135 -0
  192. data/spec/mongo/collection/view/explainable_spec.rb +32 -0
  193. data/spec/mongo/collection/view/map_reduce_spec.rb +242 -0
  194. data/spec/mongo/collection/view/readable_spec.rb +603 -0
  195. data/spec/mongo/collection/view/writable_spec.rb +504 -0
  196. data/spec/mongo/collection/view_spec.rb +521 -0
  197. data/spec/mongo/collection_spec.rb +362 -0
  198. data/spec/mongo/cursor_spec.rb +295 -0
  199. data/spec/mongo/database_spec.rb +306 -0
  200. data/spec/mongo/error/parser_spec.rb +119 -0
  201. data/spec/mongo/event/publisher_spec.rb +50 -0
  202. data/spec/mongo/event/subscriber_spec.rb +34 -0
  203. data/spec/mongo/grid/file/chunk_spec.rb +226 -0
  204. data/spec/mongo/grid/file/metadata_spec.rb +69 -0
  205. data/spec/mongo/grid/file_spec.rb +138 -0
  206. data/spec/mongo/grid/fs_spec.rb +129 -0
  207. data/spec/mongo/index/view_spec.rb +226 -0
  208. data/spec/mongo/loggable_spec.rb +62 -0
  209. data/spec/mongo/logger_spec.rb +97 -0
  210. data/spec/mongo/operation/aggregate/result_spec.rb +80 -0
  211. data/spec/mongo/operation/aggregate_spec.rb +135 -0
  212. data/spec/mongo/operation/command_spec.rb +106 -0
  213. data/spec/mongo/operation/kill_cursors_spec.rb +66 -0
  214. data/spec/mongo/operation/limited_spec.rb +50 -0
  215. data/spec/mongo/operation/map_reduce_spec.rb +143 -0
  216. data/spec/mongo/operation/read/collections_info_spec.rb +40 -0
  217. data/spec/mongo/operation/read/get_more_spec.rb +81 -0
  218. data/spec/mongo/operation/read/indexes_spec.rb +31 -0
  219. data/spec/mongo/operation/read/query_spec.rb +84 -0
  220. data/spec/mongo/operation/result_spec.rb +275 -0
  221. data/spec/mongo/operation/specifiable_spec.rb +53 -0
  222. data/spec/mongo/operation/write/bulk_delete_spec.rb +473 -0
  223. data/spec/mongo/operation/write/bulk_insert_spec.rb +466 -0
  224. data/spec/mongo/operation/write/bulk_update_spec.rb +524 -0
  225. data/spec/mongo/operation/write/command/delete_spec.rb +116 -0
  226. data/spec/mongo/operation/write/command/insert_spec.rb +117 -0
  227. data/spec/mongo/operation/write/command/update_spec.rb +123 -0
  228. data/spec/mongo/operation/write/create_user_spec.rb +44 -0
  229. data/spec/mongo/operation/write/delete_spec.rb +178 -0
  230. data/spec/mongo/operation/write/drop_index_spec.rb +51 -0
  231. data/spec/mongo/operation/write/ensure_index_spec.rb +81 -0
  232. data/spec/mongo/operation/write/insert_spec.rb +231 -0
  233. data/spec/mongo/operation/write/remove_user_spec.rb +46 -0
  234. data/spec/mongo/operation/write/response_spec.rb +85 -0
  235. data/spec/mongo/operation/write/update_spec.rb +177 -0
  236. data/spec/mongo/protocol/delete_spec.rb +167 -0
  237. data/spec/mongo/protocol/get_more_spec.rb +146 -0
  238. data/spec/mongo/protocol/insert_spec.rb +161 -0
  239. data/spec/mongo/protocol/kill_cursors_spec.rb +101 -0
  240. data/spec/mongo/protocol/query_spec.rb +285 -0
  241. data/spec/mongo/protocol/reply_spec.rb +157 -0
  242. data/spec/mongo/protocol/update_spec.rb +186 -0
  243. data/spec/mongo/server/connection_pool/queue_spec.rb +170 -0
  244. data/spec/mongo/server/connection_pool_spec.rb +120 -0
  245. data/spec/mongo/server/connection_spec.rb +289 -0
  246. data/spec/mongo/server/description/features_spec.rb +138 -0
  247. data/spec/mongo/server/description/inspector/primary_elected_spec.rb +94 -0
  248. data/spec/mongo/server/description/inspector/server_added_spec.rb +92 -0
  249. data/spec/mongo/server/description/inspector/server_removed_spec.rb +95 -0
  250. data/spec/mongo/server/description_spec.rb +510 -0
  251. data/spec/mongo/server/monitor_spec.rb +130 -0
  252. data/spec/mongo/server_discovery_and_monitoring_spec.rb +103 -0
  253. data/spec/mongo/server_selection_rtt_spec.rb +104 -0
  254. data/spec/mongo/server_selection_spec.rb +89 -0
  255. data/spec/mongo/server_selector/nearest_spec.rb +250 -0
  256. data/spec/mongo/server_selector/primary_preferred_spec.rb +290 -0
  257. data/spec/mongo/server_selector/primary_spec.rb +114 -0
  258. data/spec/mongo/server_selector/secondary_preferred_spec.rb +252 -0
  259. data/spec/mongo/server_selector/secondary_spec.rb +196 -0
  260. data/spec/mongo/server_selector_spec.rb +101 -0
  261. data/spec/mongo/server_spec.rb +131 -0
  262. data/spec/mongo/uri_spec.rb +517 -0
  263. data/spec/mongo/write_concern/acknowledged_spec.rb +44 -0
  264. data/spec/mongo/write_concern/unacknowledged_spec.rb +15 -0
  265. data/spec/mongo_orchestration_spec.rb +70 -0
  266. data/spec/spec_helper.rb +148 -0
  267. data/spec/support/authorization.rb +245 -0
  268. data/spec/support/helpers.rb +140 -0
  269. data/spec/support/matchers.rb +37 -0
  270. data/spec/support/mongo_orchestration.rb +61 -0
  271. data/spec/support/mongo_orchestration/requestable.rb +109 -0
  272. data/spec/support/mongo_orchestration/standalone.rb +57 -0
  273. data/spec/support/sdam/rs/discover_arbiters.yml +41 -0
  274. data/spec/support/sdam/rs/discover_passives.yml +41 -0
  275. data/spec/support/sdam/rs/discover_primary.yml +40 -0
  276. data/spec/support/sdam/rs/discover_secondary.yml +41 -0
  277. data/spec/support/sdam/rs/discovery.yml +195 -0
  278. data/spec/support/sdam/rs/ghost_discovered.yml +39 -0
  279. data/spec/support/sdam/rs/hosts_differ_from_seeds.yml +34 -0
  280. data/spec/support/sdam/rs/member_reconfig.yml +68 -0
  281. data/spec/support/sdam/rs/member_standalone.yml +60 -0
  282. data/spec/support/sdam/rs/new_primary.yml +74 -0
  283. data/spec/support/sdam/rs/new_primary_wrong_set_name.yml +71 -0
  284. data/spec/support/sdam/rs/non_rs_member.yml +31 -0
  285. data/spec/support/sdam/rs/normalize_case.yml +49 -0
  286. data/spec/support/sdam/rs/primary_becomes_standalone.yml +52 -0
  287. data/spec/support/sdam/rs/primary_changes_set_name.yml +57 -0
  288. data/spec/support/sdam/rs/primary_disconnect.yml +56 -0
  289. data/spec/support/sdam/rs/primary_wrong_set_name.yml +27 -0
  290. data/spec/support/sdam/rs/response_from_removed.yml +63 -0
  291. data/spec/support/sdam/rs/rsother_discovered.yml +41 -0
  292. data/spec/support/sdam/rs/sec_not_auth.yml +49 -0
  293. data/spec/support/sdam/rs/secondary_wrong_set_name.yml +28 -0
  294. data/spec/support/sdam/rs/secondary_wrong_set_name_with_primary.yml +69 -0
  295. data/spec/support/sdam/rs/unexpected_mongos.yml +26 -0
  296. data/spec/support/sdam/rs/wrong_set_name.yml +35 -0
  297. data/spec/support/sdam/sharded/multiple_mongoses.yml +46 -0
  298. data/spec/support/sdam/sharded/non_mongos_removed.yml +41 -0
  299. data/spec/support/sdam/sharded/normalize_uri_case.yml +32 -0
  300. data/spec/support/sdam/single/direct_connection_external_ip.yml +34 -0
  301. data/spec/support/sdam/single/direct_connection_mongos.yml +33 -0
  302. data/spec/support/sdam/single/direct_connection_rsarbiter.yml +35 -0
  303. data/spec/support/sdam/single/direct_connection_rsprimary.yml +34 -0
  304. data/spec/support/sdam/single/direct_connection_rssecondary.yml +35 -0
  305. data/spec/support/sdam/single/direct_connection_slave.yml +32 -0
  306. data/spec/support/sdam/single/direct_connection_standalone.yml +32 -0
  307. data/spec/support/sdam/single/not_ok_response.yml +39 -0
  308. data/spec/support/sdam/single/standalone_removed.yml +32 -0
  309. data/spec/support/sdam/single/unavailable_seed.yml +28 -0
  310. data/spec/support/server_discovery_and_monitoring.rb +167 -0
  311. data/spec/support/server_selection.rb +140 -0
  312. data/spec/support/server_selection/rtt/first_value.yml +4 -0
  313. data/spec/support/server_selection/rtt/first_value_zero.yml +4 -0
  314. data/spec/support/server_selection/rtt/value_test_1.yml +4 -0
  315. data/spec/support/server_selection/rtt/value_test_2.yml +4 -0
  316. data/spec/support/server_selection/rtt/value_test_3.yml +4 -0
  317. data/spec/support/server_selection/rtt/value_test_4.yml +4 -0
  318. data/spec/support/server_selection/rtt/value_test_5.yml +4 -0
  319. data/spec/support/server_selection/selection/ReplicaSetNoPrimary/read/Nearest.yml +32 -0
  320. data/spec/support/server_selection/selection/ReplicaSetNoPrimary/read/Nearest_non_matching.yml +27 -0
  321. data/spec/support/server_selection/selection/ReplicaSetNoPrimary/read/Primary.yml +23 -0
  322. data/spec/support/server_selection/selection/ReplicaSetNoPrimary/read/PrimaryPreferred.yml +32 -0
  323. data/spec/support/server_selection/selection/ReplicaSetNoPrimary/read/PrimaryPreferred_non_matching.yml +27 -0
  324. data/spec/support/server_selection/selection/ReplicaSetNoPrimary/read/Secondary.yml +32 -0
  325. data/spec/support/server_selection/selection/ReplicaSetNoPrimary/read/SecondaryPreferred.yml +32 -0
  326. data/spec/support/server_selection/selection/ReplicaSetNoPrimary/read/SecondaryPreferred_non_matching.yml +27 -0
  327. data/spec/support/server_selection/selection/ReplicaSetNoPrimary/read/Secondary_non_matching.yml +27 -0
  328. data/spec/support/server_selection/selection/ReplicaSetWithPrimary/read/Nearest.yml +41 -0
  329. data/spec/support/server_selection/selection/ReplicaSetWithPrimary/read/Nearest_non_matching.yml +34 -0
  330. data/spec/support/server_selection/selection/ReplicaSetWithPrimary/read/Primary.yml +33 -0
  331. data/spec/support/server_selection/selection/ReplicaSetWithPrimary/read/PrimaryPreferred.yml +39 -0
  332. data/spec/support/server_selection/selection/ReplicaSetWithPrimary/read/PrimaryPreferred_non_matching.yml +36 -0
  333. data/spec/support/server_selection/selection/Sharded/read/SecondaryPreferred.yml +32 -0
  334. data/spec/support/server_selection/selection/Single/read/SecondaryPreferred.yml +23 -0
  335. data/spec/support/server_selection/selection/Unknown/read/SecondaryPreferred.yml +13 -0
  336. data/spec/support/server_selection_rtt.rb +41 -0
  337. data/spec/support/shared/bulk_write.rb +498 -0
  338. data/spec/support/shared/cursor.rb +38 -0
  339. data/spec/support/shared/operation.rb +77 -0
  340. data/spec/support/shared/protocol.rb +31 -0
  341. data/spec/support/shared/server_selector.rb +111 -0
  342. data/spec/support/shared/socket.rb +82 -0
  343. data/spec/support/travis.rb +14 -0
  344. metadata +523 -189
  345. metadata.gz.sig +0 -0
  346. data/VERSION +0 -1
  347. data/lib/mongo/bulk_write_collection_view.rb +0 -387
  348. data/lib/mongo/collection_writer.rb +0 -364
  349. data/lib/mongo/connection/node.rb +0 -249
  350. data/lib/mongo/connection/pool.rb +0 -340
  351. data/lib/mongo/connection/pool_manager.rb +0 -320
  352. data/lib/mongo/connection/sharding_pool_manager.rb +0 -67
  353. data/lib/mongo/connection/socket/ssl_socket.rb +0 -95
  354. data/lib/mongo/connection/socket/tcp_socket.rb +0 -87
  355. data/lib/mongo/connection/socket/unix_socket.rb +0 -39
  356. data/lib/mongo/db.rb +0 -808
  357. data/lib/mongo/exception.rb +0 -145
  358. data/lib/mongo/functional/authentication.rb +0 -455
  359. data/lib/mongo/functional/logging.rb +0 -85
  360. data/lib/mongo/functional/read_preference.rb +0 -183
  361. data/lib/mongo/functional/scram.rb +0 -556
  362. data/lib/mongo/functional/uri_parser.rb +0 -409
  363. data/lib/mongo/functional/write_concern.rb +0 -66
  364. data/lib/mongo/gridfs/grid.rb +0 -112
  365. data/lib/mongo/gridfs/grid_ext.rb +0 -53
  366. data/lib/mongo/gridfs/grid_file_system.rb +0 -163
  367. data/lib/mongo/gridfs/grid_io.rb +0 -484
  368. data/lib/mongo/legacy.rb +0 -140
  369. data/lib/mongo/mongo_client.rb +0 -697
  370. data/lib/mongo/mongo_replica_set_client.rb +0 -535
  371. data/lib/mongo/mongo_sharded_client.rb +0 -159
  372. data/lib/mongo/networking.rb +0 -372
  373. data/lib/mongo/utils/conversions.rb +0 -110
  374. data/lib/mongo/utils/core_ext.rb +0 -70
  375. data/lib/mongo/utils/server_version.rb +0 -69
  376. data/lib/mongo/utils/support.rb +0 -80
  377. data/test/functional/authentication_test.rb +0 -39
  378. data/test/functional/bulk_api_stress_test.rb +0 -133
  379. data/test/functional/bulk_write_collection_view_test.rb +0 -1198
  380. data/test/functional/client_test.rb +0 -627
  381. data/test/functional/collection_test.rb +0 -2175
  382. data/test/functional/collection_writer_test.rb +0 -83
  383. data/test/functional/conversions_test.rb +0 -163
  384. data/test/functional/cursor_fail_test.rb +0 -57
  385. data/test/functional/cursor_message_test.rb +0 -56
  386. data/test/functional/cursor_test.rb +0 -683
  387. data/test/functional/db_api_test.rb +0 -835
  388. data/test/functional/db_test.rb +0 -348
  389. data/test/functional/grid_file_system_test.rb +0 -285
  390. data/test/functional/grid_io_test.rb +0 -252
  391. data/test/functional/grid_test.rb +0 -273
  392. data/test/functional/pool_test.rb +0 -136
  393. data/test/functional/safe_test.rb +0 -98
  394. data/test/functional/support_test.rb +0 -62
  395. data/test/functional/timeout_test.rb +0 -60
  396. data/test/functional/uri_test.rb +0 -446
  397. data/test/functional/write_concern_test.rb +0 -118
  398. data/test/helpers/general.rb +0 -50
  399. data/test/helpers/test_unit.rb +0 -476
  400. data/test/replica_set/authentication_test.rb +0 -37
  401. data/test/replica_set/basic_test.rb +0 -189
  402. data/test/replica_set/client_test.rb +0 -393
  403. data/test/replica_set/connection_test.rb +0 -138
  404. data/test/replica_set/count_test.rb +0 -66
  405. data/test/replica_set/cursor_test.rb +0 -220
  406. data/test/replica_set/insert_test.rb +0 -157
  407. data/test/replica_set/max_values_test.rb +0 -151
  408. data/test/replica_set/pinning_test.rb +0 -105
  409. data/test/replica_set/query_test.rb +0 -73
  410. data/test/replica_set/read_preference_test.rb +0 -219
  411. data/test/replica_set/refresh_test.rb +0 -211
  412. data/test/replica_set/replication_ack_test.rb +0 -95
  413. data/test/sharded_cluster/basic_test.rb +0 -203
  414. data/test/shared/authentication/basic_auth_shared.rb +0 -260
  415. data/test/shared/authentication/bulk_api_auth_shared.rb +0 -249
  416. data/test/shared/authentication/gssapi_shared.rb +0 -176
  417. data/test/shared/authentication/sasl_plain_shared.rb +0 -96
  418. data/test/shared/authentication/scram_shared.rb +0 -92
  419. data/test/shared/ssl_shared.rb +0 -235
  420. data/test/test_helper.rb +0 -61
  421. data/test/threading/basic_test.rb +0 -120
  422. data/test/tools/mongo_config.rb +0 -708
  423. data/test/tools/mongo_config_test.rb +0 -160
  424. data/test/unit/client_test.rb +0 -381
  425. data/test/unit/collection_test.rb +0 -166
  426. data/test/unit/connection_test.rb +0 -335
  427. data/test/unit/cursor_test.rb +0 -307
  428. data/test/unit/db_test.rb +0 -136
  429. data/test/unit/grid_test.rb +0 -76
  430. data/test/unit/mongo_sharded_client_test.rb +0 -48
  431. data/test/unit/node_test.rb +0 -93
  432. data/test/unit/pool_manager_test.rb +0 -111
  433. data/test/unit/read_pref_test.rb +0 -406
  434. data/test/unit/read_test.rb +0 -159
  435. data/test/unit/safe_test.rb +0 -158
  436. data/test/unit/sharding_pool_manager_test.rb +0 -84
  437. data/test/unit/write_concern_test.rb +0 -175
@@ -0,0 +1,91 @@
1
+ # Copyright (C) 2014-2015 MongoDB, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module Mongo
16
+
17
+ module ServerSelector
18
+
19
+ # Encapsulates specifications for selecting secondary servers given a list
20
+ # of candidates.
21
+ #
22
+ # @since 2.0.0
23
+ class Secondary
24
+ include Selectable
25
+
26
+ # Get the name of the server mode type.
27
+ #
28
+ # @example Get the name of the server mode for this preference.
29
+ # preference.name
30
+ #
31
+ # @return [ Symbol ] :secondary
32
+ #
33
+ # @since 2.0.0
34
+ def name
35
+ :secondary
36
+ end
37
+
38
+ # Whether the slaveOk bit should be set on wire protocol messages.
39
+ # I.e. whether the operation can be performed on a secondary server.
40
+ #
41
+ # @return [ true ] true
42
+ #
43
+ # @since 2.0.0
44
+ def slave_ok?
45
+ true
46
+ end
47
+
48
+ # Whether tag sets are allowed to be defined for this server preference.
49
+ #
50
+ # @return [ true ] true
51
+ #
52
+ # @since 2.0.0
53
+ def tags_allowed?
54
+ true
55
+ end
56
+
57
+ # Convert this server preference definition into a format appropriate
58
+ # for a mongos server.
59
+ #
60
+ # @example Convert this server preference definition into a format
61
+ # for mongos.
62
+ # preference = Mongo::ServerSelector::Secondary.new
63
+ # preference.to_mongos
64
+ #
65
+ # @return [ Hash ] The server preference formatted for a mongos server.
66
+ #
67
+ # @since 2.0.0
68
+ def to_mongos
69
+ preference = { :mode => 'secondary' }
70
+ preference.merge!({ :tags => tag_sets }) unless tag_sets.empty?
71
+ preference
72
+ end
73
+
74
+ private
75
+
76
+ # Select the secondary servers taking into account any defined tag sets and
77
+ # local threshold between the nearest secondary and other secondaries.
78
+ #
79
+ # @example Select secondary servers given a list of candidates.
80
+ # preference = Mongo::ServerSelector::Secondary.new
81
+ # preference.select([candidate_1, candidate_2])
82
+ #
83
+ # @return [ Array ] The secondary servers from the list of candidates.
84
+ #
85
+ # @since 2.0.0
86
+ def select(candidates)
87
+ near_servers(secondaries(candidates))
88
+ end
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,96 @@
1
+ # Copyright (C) 2014-2015 MongoDB, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module Mongo
16
+
17
+ module ServerSelector
18
+
19
+ # Encapsulates specifications for selecting servers, with
20
+ # secondaries preferred, given a list of candidates.
21
+ #
22
+ # @since 2.0.0
23
+ class SecondaryPreferred
24
+ include Selectable
25
+
26
+ # Get the name of the server mode type.
27
+ #
28
+ # @example Get the name of the server mode for this preference.
29
+ # preference.name
30
+ #
31
+ # @return [ Symbol ] :secondary_preferred
32
+ #
33
+ # @since 2.0.0
34
+ def name
35
+ :secondary_preferred
36
+ end
37
+
38
+ # Whether the slaveOk bit should be set on wire protocol messages.
39
+ # I.e. whether the operation can be performed on a secondary server.
40
+ #
41
+ # @return [ true ] true
42
+ #
43
+ # @since 2.0.0
44
+ def slave_ok?
45
+ true
46
+ end
47
+
48
+ # Whether tag sets are allowed to be defined for this server preference.
49
+ #
50
+ # @return [ true ] true
51
+ #
52
+ # @since 2.0.0
53
+ def tags_allowed?
54
+ true
55
+ end
56
+
57
+ # Convert this server preference definition into a format appropriate
58
+ # for a mongos server.
59
+ # Note that the server preference is not sent to mongos as part of the query
60
+ # selector if there are no tag sets, for maximum backwards compatibility.
61
+ #
62
+ # @example Convert this server preference definition into a format
63
+ # for mongos.
64
+ # preference = Mongo::ServerSelector::SecondaryPreferred.new
65
+ # preference.to_mongos
66
+ #
67
+ # @return [ Hash ] The server preference formatted for a mongos server.
68
+ #
69
+ # @since 2.0.0
70
+ def to_mongos
71
+ return nil if tag_sets.empty?
72
+ preference = { mode: 'secondaryPreferred' }
73
+ preference.merge!({ tags: tag_sets })
74
+ preference
75
+ end
76
+
77
+ private
78
+
79
+ # Select servers taking into account any defined tag sets and
80
+ # local threshold, with secondaries.
81
+ #
82
+ # @example Select servers given a list of candidates,
83
+ # with secondaries preferred.
84
+ # preference = Mongo::ServerSelector::SecondaryPreferred.new
85
+ # preference.select([candidate_1, candidate_2])
86
+ #
87
+ # @return [ Array ] A list of servers matching tag sets and acceptable
88
+ # latency with secondaries preferred.
89
+ #
90
+ # @since 2.0.0
91
+ def select(candidates)
92
+ near_servers(secondaries(candidates)) + primary(candidates)
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,209 @@
1
+ # Copyright (C) 2014-2015 MongoDB, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module Mongo
16
+ module ServerSelector
17
+
18
+ # Provides common behavior for filtering a list of servers by server mode or tag set.
19
+ #
20
+ # @since 2.0.0
21
+ module Selectable
22
+
23
+ # The max latency in seconds between the closest server and other servers
24
+ # considered for selection.
25
+ #
26
+ # @since 2.0.0
27
+ LOCAL_THRESHOLD = 0.015.freeze
28
+
29
+ # How long to block for server selection before throwing an exception.
30
+ #
31
+ # @since 2.0.0
32
+ SERVER_SELECTION_TIMEOUT = 30.freeze
33
+
34
+ # @return [ Hash ] options The options.
35
+ attr_reader :options
36
+
37
+ # @return [ Array ] tag_sets The tag sets used to select servers.
38
+ attr_reader :tag_sets
39
+
40
+ # Check equality of two server selector.
41
+ #
42
+ # @example Check server selector equality.
43
+ # preference == other
44
+ #
45
+ # @param [ Object ] other The other preference.
46
+ #
47
+ # @return [ true, false ] Whether the objects are equal.
48
+ #
49
+ # @since 2.0.0
50
+ def ==(other)
51
+ name == other.name && tag_sets == other.tag_sets
52
+ end
53
+
54
+ # Initialize the server selector.
55
+ #
56
+ # @example Initialize the preference with tag sets.
57
+ # Mongo::ServerSelector::Secondary.new([{ 'tag' => 'set' }])
58
+ #
59
+ # @example Initialize the preference with no options.
60
+ # Mongo::ServerSelector::Secondary.new
61
+ #
62
+ # @param [ Array ] tag_sets The tag sets used to select servers.
63
+ #
64
+ # @todo: document specific error
65
+ # @raise [ Exception ] If tag sets are specified but not allowed.
66
+ #
67
+ # @since 2.0.0
68
+ def initialize(tag_sets = [], options = {})
69
+ if !tag_sets.all? { |set| set.empty? } && !tags_allowed?
70
+ raise ServerSelector::InvalidServerPreference.new(name)
71
+ end
72
+ @tag_sets = tag_sets
73
+ @options = options
74
+ end
75
+
76
+ # Select a server from eligible candidates.
77
+ #
78
+ # @example Select a server from the cluster.
79
+ # selector.select_server(cluster)
80
+ #
81
+ # @param [ Mongo::Cluster ] cluster The cluster from which to select an eligible server.
82
+ #
83
+ # @return [ Mongo::Server ] A server matching the server preference.
84
+ #
85
+ # @since 2.0.0
86
+ def select_server(cluster)
87
+ deadline = Time.now + server_selection_timeout
88
+ while (deadline - Time.now) > 0
89
+ if cluster.standalone?
90
+ servers = cluster.servers
91
+ elsif cluster.sharded?
92
+ servers = near_servers(cluster.servers)
93
+ else
94
+ servers = select(cluster.servers)
95
+ end
96
+ return servers.first if servers && !servers.compact.empty?
97
+ cluster.scan!
98
+ end
99
+ raise NoServerAvailable.new(self)
100
+ end
101
+
102
+ # Get the timeout for server selection.
103
+ #
104
+ # @example Get the server selection timeout, in seconds.
105
+ # selector.server_selection_timeout
106
+ #
107
+ # @return [ Float ] The timeout.
108
+ #
109
+ # @since 2.0.0
110
+ def server_selection_timeout
111
+ @server_selection_timeout ||=
112
+ (options[:server_selection_timeout] || SERVER_SELECTION_TIMEOUT)
113
+ end
114
+
115
+ # Get the local threshold boundary for nearest selection in seconds.
116
+ #
117
+ # @example Get the local threshold.
118
+ # selector.local_threshold
119
+ #
120
+ # @return [ Float ] The local threshold.
121
+ #
122
+ # @since 2.0.0
123
+ def local_threshold
124
+ @local_threshold ||= (options[:local_threshold] || LOCAL_THRESHOLD)
125
+ end
126
+
127
+ private
128
+
129
+ # Select the primary from a list of provided candidates.
130
+ #
131
+ # @param [ Array ] candidates List of candidate servers to select the
132
+ # primary from.
133
+ #
134
+ # @return [ Array ] The primary.
135
+ #
136
+ # @since 2.0.0
137
+ def primary(candidates)
138
+ candidates.select do |server|
139
+ server.primary? || server.standalone?
140
+ end
141
+ end
142
+
143
+ # Select the secondaries from a list of provided candidates.
144
+ #
145
+ # @param [ Array ] candidates List of candidate servers to select the
146
+ # secondaries from.
147
+ #
148
+ # @return [ Array ] The secondary servers.
149
+ #
150
+ # @since 2.0.0
151
+ def secondaries(candidates)
152
+ matching_servers = candidates.select(&:secondary?)
153
+ matching_servers = match_tag_sets(matching_servers) unless tag_sets.empty?
154
+ matching_servers
155
+ end
156
+
157
+ # Select the near servers from a list of provided candidates, taking the
158
+ # local threshold into account.
159
+ #
160
+ # @param [ Array ] candidates List of candidate servers to select the
161
+ # near servers from.
162
+ #
163
+ # @return [ Array ] The near servers.
164
+ #
165
+ # @since 2.0.0
166
+ def near_servers(candidates = [])
167
+ return candidates if candidates.empty?
168
+ nearest_server = candidates.min_by(&:average_round_trip_time)
169
+ threshold = nearest_server.average_round_trip_time + (local_threshold * 1000)
170
+ candidates.select { |server| server.average_round_trip_time <= threshold }.shuffle!
171
+ end
172
+
173
+ # Select the servers matching the defined tag sets.
174
+ #
175
+ # @param [ Array ] candidates List of candidate servers from which those
176
+ # matching the defined tag sets should be selected.
177
+ #
178
+ # @return [ Array ] The servers matching the defined tag sets.
179
+ #
180
+ # @since 2.0.0
181
+ def match_tag_sets(candidates)
182
+ matches = []
183
+ tag_sets.find do |tag_set|
184
+ matches = candidates.select { |server| server.matches_tag_set?(tag_set) }
185
+ !matches.empty?
186
+ end
187
+ matches || []
188
+ end
189
+ end
190
+
191
+ # Raised when an invalid server preference is provided.
192
+ #
193
+ # @since 2.0.0
194
+ class InvalidServerPreference < Error
195
+
196
+ # Instantiate the new exception.
197
+ #
198
+ # @example Instantiate the exception.
199
+ # Mongo::ServerSelector::InvalidServerPreference.new
200
+ #
201
+ # @param [ String ] name The preference name.
202
+ #
203
+ # @since 2.0.0
204
+ def initialize(name)
205
+ super("This server preference #{name} cannot be combined with tags.")
206
+ end
207
+ end
208
+ end
209
+ end
@@ -0,0 +1,179 @@
1
+ # Copyright (C) 2014-2015 MongoDB, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require 'socket'
16
+ require 'timeout'
17
+ require 'mongo/socket/ssl'
18
+ require 'mongo/socket/tcp'
19
+ require 'mongo/socket/unix'
20
+
21
+ module Mongo
22
+
23
+ # Provides additional data around sockets for the driver's use.
24
+ #
25
+ # @since 2.0.0
26
+ class Socket
27
+ include ::Socket::Constants
28
+
29
+ # Error message for SSL related exceptions.
30
+ #
31
+ # @since 2.0.0
32
+ SSL_ERROR = 'SSL handshake failed. MongoDB may not be configured with SSL support.'.freeze
33
+
34
+ # Error message for timeouts on socket calls.
35
+ #
36
+ # @since 2.0.0
37
+ TIMEOUT_ERROR = 'Socket request timed out'.freeze
38
+
39
+ # The pack directive for timeouts.
40
+ #
41
+ # @since 2.0.0
42
+ TIMEOUT_PACK = 'l_2'.freeze
43
+
44
+ # @return [ Integer ] family The type of host family.
45
+ attr_reader :family
46
+
47
+ # @return [ Socket ] socket The wrapped socket.
48
+ attr_reader :socket
49
+
50
+ # Is the socket connection alive?
51
+ #
52
+ # @example Is the socket alive?
53
+ # socket.alive?
54
+ #
55
+ # @return [ true, false ] If the socket is alive.
56
+ #
57
+ # @since 2.0.0
58
+ def alive?
59
+ if Kernel::select([ socket ], nil, [ socket ], 0)
60
+ !eof? rescue false
61
+ else
62
+ true
63
+ end
64
+ rescue IOError
65
+ false
66
+ end
67
+
68
+ # Close the socket.
69
+ #
70
+ # @example Close the socket.
71
+ # socket.close
72
+ #
73
+ # @return [ true ] Always true.
74
+ #
75
+ # @since 2.0.0
76
+ def close
77
+ socket.close rescue true
78
+ true
79
+ end
80
+
81
+ # Delegates gets to the underlying socket.
82
+ #
83
+ # @example Get the next line.
84
+ # socket.gets(10)
85
+ #
86
+ # @param [ Array<Object> ] args The arguments to pass through.
87
+ #
88
+ # @return [ Object ] The returned bytes.
89
+ #
90
+ # @since 2.0.0
91
+ def gets(*args)
92
+ handle_errors { socket.gets(*args) }
93
+ end
94
+
95
+ # Create the new socket for the provided family - ipv4, piv6, or unix.
96
+ #
97
+ # @example Create a new ipv4 socket.
98
+ # Socket.new(Socket::PF_INET)
99
+ #
100
+ # @param [ Integer ] family The socket domain.
101
+ #
102
+ # @since 2.0.0
103
+ def initialize(family)
104
+ @family = family
105
+ @socket = ::Socket.new(family, SOCK_STREAM, 0)
106
+ encoded_timeout = [ timeout, 0 ].pack(TIMEOUT_PACK)
107
+ socket.set_encoding(BSON::BINARY)
108
+ socket.setsockopt(SOL_SOCKET, SO_RCVTIMEO, encoded_timeout)
109
+ socket.setsockopt(SOL_SOCKET, SO_SNDTIMEO, encoded_timeout)
110
+ end
111
+
112
+ # Will read all data from the socket for the provided number of bytes.
113
+ # If less data is returned than requested, an exception will be raised.
114
+ #
115
+ # @example Read all the requested data from the socket.
116
+ # socket.read(4096)
117
+ #
118
+ # @param [ Integer ] length The number of bytes to read.
119
+ #
120
+ # @raise [ Mongo::SocketError ] If not all data is returned.
121
+ #
122
+ # @return [ Object ] The data from the socket.
123
+ #
124
+ # @since 2.0.0
125
+ def read(length)
126
+ handle_errors do
127
+ data = read_from_socket(length)
128
+ while data.length < length
129
+ data << read_from_socket(length - data.length)
130
+ end
131
+ data
132
+ end
133
+ end
134
+
135
+ # Read a single byte from the socket.
136
+ #
137
+ # @example Read a single byte.
138
+ # socket.readbyte
139
+ #
140
+ # @return [ Object ] The read byte.
141
+ #
142
+ # @since 2.0.0
143
+ def readbyte
144
+ handle_errors { socket.readbyte }
145
+ end
146
+
147
+ # Writes data to the socket instance.
148
+ #
149
+ # @example Write to the socket.
150
+ # socket.write(data)
151
+ #
152
+ # @param [ Array<Object> ] args The data to be written.
153
+ #
154
+ # @return [ Integer ] The length of bytes written to the socket.
155
+ #
156
+ # @since 2.0.0
157
+ def write(*args)
158
+ handle_errors { socket.write(*args) }
159
+ end
160
+
161
+ private
162
+
163
+ def read_from_socket(length)
164
+ socket.read(length) || String.new
165
+ end
166
+
167
+ def handle_errors
168
+ begin
169
+ yield
170
+ rescue Errno::ETIMEDOUT
171
+ raise Error::SocketTimeoutError, TIMEOUT_ERROR
172
+ rescue IOError, SystemCallError => e
173
+ raise Error::SocketError, e.message
174
+ rescue OpenSSL::SSL::SSLError
175
+ raise Error::SocketError, SSL_ERROR
176
+ end
177
+ end
178
+ end
179
+ end