mongo 2.1.0.beta → 2.1.0.rc0

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 (253) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/Rakefile +2 -2
  5. data/lib/mongo.rb +2 -3
  6. data/lib/mongo/address.rb +7 -5
  7. data/lib/mongo/address/unix.rb +2 -2
  8. data/lib/mongo/auth/ldap/conversation.rb +6 -2
  9. data/lib/mongo/auth/scram/conversation.rb +8 -2
  10. data/lib/mongo/auth/user/view.rb +21 -0
  11. data/lib/mongo/bulk_write.rb +155 -23
  12. data/lib/mongo/bulk_write/combineable.rb +51 -0
  13. data/lib/mongo/bulk_write/ordered_combiner.rb +55 -0
  14. data/lib/mongo/bulk_write/result.rb +61 -8
  15. data/lib/mongo/bulk_write/result_combiner.rb +117 -0
  16. data/lib/mongo/bulk_write/transformable.rb +117 -0
  17. data/lib/mongo/bulk_write/unordered_combiner.rb +52 -0
  18. data/lib/mongo/bulk_write/validatable.rb +62 -0
  19. data/lib/mongo/client.rb +7 -3
  20. data/lib/mongo/cluster.rb +3 -3
  21. data/lib/mongo/cluster/topology/replica_set.rb +8 -6
  22. data/lib/mongo/cluster/topology/unknown.rb +5 -2
  23. data/lib/mongo/collection.rb +75 -4
  24. data/lib/mongo/collection/view.rb +1 -2
  25. data/lib/mongo/collection/view/aggregation.rb +13 -8
  26. data/lib/mongo/collection/view/immutable.rb +6 -6
  27. data/lib/mongo/collection/view/iterable.rb +13 -4
  28. data/lib/mongo/collection/view/map_reduce.rb +22 -17
  29. data/lib/mongo/collection/view/readable.rb +121 -70
  30. data/lib/mongo/cursor.rb +5 -1
  31. data/lib/mongo/database.rb +3 -3
  32. data/lib/mongo/database/view.rb +1 -1
  33. data/lib/mongo/error.rb +7 -0
  34. data/lib/mongo/{bulk_write/unordered_bulk_write.rb → error/closed_stream.rb} +12 -21
  35. data/lib/mongo/{bulk_write/ordered_bulk_write.rb → error/extra_file_chunk.rb} +13 -27
  36. data/lib/mongo/error/file_not_found.rb +37 -0
  37. data/lib/mongo/error/invalid_file.rb +2 -2
  38. data/lib/mongo/error/invalid_file_revision.rb +37 -0
  39. data/lib/mongo/error/invalid_uri.rb +5 -4
  40. data/lib/mongo/error/missing_file_chunk.rb +38 -0
  41. data/lib/mongo/error/operation_failure.rb +1 -1
  42. data/lib/mongo/error/unchangeable_collection_option.rb +38 -0
  43. data/lib/mongo/error/unexpected_chunk_length.rb +39 -0
  44. data/lib/mongo/grid.rb +2 -1
  45. data/lib/mongo/grid/file.rb +12 -9
  46. data/lib/mongo/grid/file/chunk.rb +6 -6
  47. data/lib/mongo/grid/file/{metadata.rb → info.rb} +41 -39
  48. data/lib/mongo/grid/fs_bucket.rb +441 -0
  49. data/lib/mongo/grid/stream.rb +64 -0
  50. data/lib/mongo/grid/stream/read.rb +208 -0
  51. data/lib/mongo/grid/stream/write.rb +187 -0
  52. data/lib/mongo/index/view.rb +1 -1
  53. data/lib/mongo/loggable.rb +34 -57
  54. data/lib/mongo/logger.rb +16 -78
  55. data/lib/mongo/monitoring.rb +1 -5
  56. data/lib/mongo/monitoring/command_log_subscriber.rb +35 -17
  57. data/lib/mongo/monitoring/event/command_succeeded.rb +20 -1
  58. data/lib/mongo/monitoring/publishable.rb +22 -12
  59. data/lib/mongo/operation.rb +3 -6
  60. data/lib/mongo/operation/commands.rb +24 -0
  61. data/lib/mongo/operation/{aggregate.rb → commands/aggregate.rb} +3 -41
  62. data/lib/mongo/operation/{aggregate → commands/aggregate}/result.rb +0 -0
  63. data/lib/mongo/operation/commands/collections_info.rb +66 -0
  64. data/lib/mongo/operation/{command.rb → commands/command.rb} +2 -18
  65. data/lib/mongo/operation/commands/indexes.rb +70 -0
  66. data/lib/mongo/operation/commands/list_collections.rb +54 -0
  67. data/lib/mongo/operation/commands/list_collections/result.rb +112 -0
  68. data/lib/mongo/operation/commands/list_indexes.rb +56 -0
  69. data/lib/mongo/operation/commands/list_indexes/result.rb +115 -0
  70. data/lib/mongo/operation/{map_reduce.rb → commands/map_reduce.rb} +3 -41
  71. data/lib/mongo/operation/{map_reduce → commands/map_reduce}/result.rb +0 -0
  72. data/lib/mongo/operation/{parallel_scan.rb → commands/parallel_scan.rb} +3 -23
  73. data/lib/mongo/operation/{parallel_scan → commands/parallel_scan}/result.rb +0 -0
  74. data/lib/mongo/operation/commands/user_query.rb +69 -0
  75. data/lib/mongo/operation/commands/users_info.rb +53 -0
  76. data/lib/mongo/operation/commands/users_info/result.rb +36 -0
  77. data/lib/mongo/operation/executable.rb +4 -68
  78. data/lib/mongo/operation/kill_cursors.rb +3 -3
  79. data/lib/mongo/operation/read.rb +0 -4
  80. data/lib/mongo/operation/read/get_more.rb +2 -22
  81. data/lib/mongo/operation/read/query.rb +2 -21
  82. data/lib/mongo/operation/{read_preferrable.rb → read_preference.rb} +3 -2
  83. data/lib/mongo/operation/specifiable.rb +24 -0
  84. data/lib/mongo/operation/write.rb +2 -0
  85. data/lib/mongo/operation/write/bulk.rb +6 -3
  86. data/lib/mongo/operation/write/bulk/bulkable.rb +82 -0
  87. data/lib/mongo/operation/write/bulk/delete.rb +71 -0
  88. data/lib/mongo/operation/write/bulk/delete/result.rb +74 -0
  89. data/lib/mongo/operation/write/bulk/insert.rb +96 -0
  90. data/lib/mongo/operation/write/bulk/insert/result.rb +129 -0
  91. data/lib/mongo/operation/write/bulk/legacy_mergable.rb +87 -0
  92. data/lib/mongo/operation/write/bulk/mergable.rb +71 -0
  93. data/lib/mongo/operation/write/bulk/update.rb +81 -0
  94. data/lib/mongo/operation/write/bulk/update/result.rb +174 -0
  95. data/lib/mongo/operation/write/command/create_index.rb +0 -1
  96. data/lib/mongo/operation/write/command/create_user.rb +0 -1
  97. data/lib/mongo/operation/write/command/delete.rb +0 -1
  98. data/lib/mongo/operation/write/command/drop_index.rb +0 -1
  99. data/lib/mongo/operation/write/command/insert.rb +0 -1
  100. data/lib/mongo/operation/write/command/remove_user.rb +0 -1
  101. data/lib/mongo/operation/write/command/update.rb +0 -1
  102. data/lib/mongo/operation/write/command/update_user.rb +0 -1
  103. data/lib/mongo/operation/write/command/writable.rb +13 -18
  104. data/lib/mongo/operation/write/create_index.rb +4 -27
  105. data/lib/mongo/operation/write/create_user.rb +4 -30
  106. data/lib/mongo/operation/write/delete.rb +5 -28
  107. data/lib/mongo/operation/write/drop_index.rb +3 -3
  108. data/lib/mongo/operation/write/gle.rb +48 -0
  109. data/lib/mongo/operation/write/idable.rb +5 -0
  110. data/lib/mongo/operation/write/insert.rb +2 -24
  111. data/lib/mongo/operation/write/remove_user.rb +4 -27
  112. data/lib/mongo/operation/write/update.rb +4 -32
  113. data/lib/mongo/operation/write/update_user.rb +4 -30
  114. data/lib/mongo/operation/write/write_command_enabled.rb +53 -0
  115. data/lib/mongo/options/mapper.rb +4 -2
  116. data/lib/mongo/protocol/delete.rb +68 -3
  117. data/lib/mongo/protocol/get_more.rb +54 -2
  118. data/lib/mongo/protocol/insert.rb +59 -1
  119. data/lib/mongo/protocol/kill_cursors.rb +53 -4
  120. data/lib/mongo/protocol/message.rb +12 -12
  121. data/lib/mongo/protocol/query.rb +139 -65
  122. data/lib/mongo/protocol/reply.rb +69 -1
  123. data/lib/mongo/protocol/update.rb +70 -1
  124. data/lib/mongo/server/connection.rb +11 -3
  125. data/lib/mongo/server/description.rb +29 -0
  126. data/lib/mongo/server/description/features.rb +2 -1
  127. data/lib/mongo/server/monitor.rb +2 -2
  128. data/lib/mongo/server_selector.rb +14 -10
  129. data/lib/mongo/server_selector/selectable.rb +24 -22
  130. data/lib/mongo/socket.rb +6 -3
  131. data/lib/mongo/socket/tcp.rb +2 -2
  132. data/lib/mongo/socket/unix.rb +5 -8
  133. data/lib/mongo/uri.rb +243 -139
  134. data/lib/mongo/version.rb +1 -1
  135. data/spec/mongo/address/unix_spec.rb +1 -1
  136. data/spec/mongo/address_spec.rb +25 -0
  137. data/spec/mongo/auth/ldap/conversation_spec.rb +43 -0
  138. data/spec/mongo/auth/user/view_spec.rb +26 -1
  139. data/spec/mongo/bulk_write/ordered_combiner_spec.rb +271 -0
  140. data/spec/mongo/bulk_write/unordered_combiner_spec.rb +239 -0
  141. data/spec/mongo/bulk_write_spec.rb +332 -166
  142. data/spec/mongo/client_spec.rb +25 -0
  143. data/spec/mongo/cluster/topology/replica_set_spec.rb +2 -0
  144. data/spec/mongo/collection/view/aggregation_spec.rb +65 -0
  145. data/spec/mongo/collection/view/immutable_spec.rb +103 -0
  146. data/spec/mongo/collection/view/map_reduce_spec.rb +98 -3
  147. data/spec/mongo/collection/view/readable_spec.rb +17 -30
  148. data/spec/mongo/collection/view_spec.rb +233 -7
  149. data/spec/mongo/collection_spec.rb +360 -18
  150. data/spec/mongo/command_monitoring_spec.rb +51 -0
  151. data/spec/mongo/connection_string_spec.rb +137 -0
  152. data/spec/mongo/database_spec.rb +27 -11
  153. data/spec/mongo/grid/file/chunk_spec.rb +5 -5
  154. data/spec/mongo/grid/file/{metadata_spec.rb → info_spec.rb} +29 -17
  155. data/spec/mongo/grid/file_spec.rb +8 -8
  156. data/spec/mongo/grid/fs_bucket_spec.rb +1020 -0
  157. data/spec/mongo/grid/stream/read_spec.rb +275 -0
  158. data/spec/mongo/grid/stream/write_spec.rb +440 -0
  159. data/spec/mongo/grid/stream_spec.rb +48 -0
  160. data/spec/mongo/gridfs_spec.rb +50 -0
  161. data/spec/mongo/logger_spec.rb +0 -40
  162. data/spec/mongo/monitoring/command_log_subscriber_spec.rb +76 -0
  163. data/spec/mongo/operation/{aggregate_spec.rb → commands/aggregate_spec.rb} +0 -42
  164. data/spec/mongo/operation/{read → commands}/collections_info_spec.rb +1 -1
  165. data/spec/mongo/operation/{command_spec.rb → commands/command_spec.rb} +0 -0
  166. data/spec/mongo/operation/{read → commands}/indexes_spec.rb +1 -1
  167. data/spec/mongo/operation/{map_reduce_spec.rb → commands/map_reduce_spec.rb} +0 -18
  168. data/spec/mongo/operation/kill_cursors_spec.rb +1 -1
  169. data/spec/mongo/operation/{read_preferrable_spec.rb → read_preference_spec.rb} +11 -11
  170. data/spec/mongo/operation/write/bulk/{bulk_delete_spec.rb → delete_spec.rb} +1 -12
  171. data/spec/mongo/operation/write/bulk/{bulk_insert_spec.rb → insert_spec.rb} +1 -12
  172. data/spec/mongo/operation/write/bulk/{bulk_update_spec.rb → update_spec.rb} +1 -12
  173. data/spec/mongo/operation/write/insert_spec.rb +0 -11
  174. data/spec/mongo/protocol/kill_cursors_spec.rb +5 -3
  175. data/spec/mongo/server/description_spec.rb +42 -0
  176. data/spec/mongo/server/monitor_spec.rb +21 -0
  177. data/spec/mongo/server_discovery_and_monitoring_spec.rb +1 -0
  178. data/spec/mongo/server_selection_spec.rb +3 -3
  179. data/spec/mongo/server_selector/nearest_spec.rb +34 -27
  180. data/spec/mongo/server_selector/primary_preferred_spec.rb +31 -30
  181. data/spec/mongo/server_selector/primary_spec.rb +14 -13
  182. data/spec/mongo/server_selector/secondary_preferred_spec.rb +27 -26
  183. data/spec/mongo/server_selector/secondary_spec.rb +23 -22
  184. data/spec/mongo/server_selector_spec.rb +87 -24
  185. data/spec/mongo/socket/unix_spec.rb +52 -0
  186. data/spec/mongo/uri_spec.rb +251 -39
  187. data/spec/spec_helper.rb +11 -4
  188. data/spec/support/authorization.rb +4 -5
  189. data/spec/support/command_monitoring.rb +365 -0
  190. data/spec/support/command_monitoring/bulkWrite.yml +73 -0
  191. data/spec/support/command_monitoring/command.yml +42 -0
  192. data/spec/support/command_monitoring/deleteMany.yml +55 -0
  193. data/spec/support/command_monitoring/deleteOne.yml +55 -0
  194. data/spec/support/command_monitoring/find.yml +219 -0
  195. data/spec/support/command_monitoring/insertMany.yml +81 -0
  196. data/spec/support/command_monitoring/insertOne.yml +51 -0
  197. data/spec/support/command_monitoring/updateMany.yml +67 -0
  198. data/spec/support/command_monitoring/updateOne.yml +95 -0
  199. data/spec/support/connection_string.rb +228 -0
  200. data/spec/support/connection_string_tests/invalid-uris.yml +193 -0
  201. data/spec/support/connection_string_tests/valid-auth.yml +256 -0
  202. data/spec/support/connection_string_tests/valid-host_identifiers.yml +121 -0
  203. data/spec/support/connection_string_tests/valid-options.yml +30 -0
  204. data/spec/support/connection_string_tests/valid-unix_socket-absolute.yml +197 -0
  205. data/spec/support/connection_string_tests/valid-unix_socket-relative.yml +213 -0
  206. data/spec/support/connection_string_tests/valid-warnings.yml +55 -0
  207. data/spec/support/crud.rb +3 -1
  208. data/spec/support/crud/read.rb +14 -10
  209. data/spec/support/crud/write.rb +36 -9
  210. data/spec/support/gridfs.rb +637 -0
  211. data/spec/support/gridfs_tests/delete.yml +157 -0
  212. data/spec/support/gridfs_tests/download.yml +210 -0
  213. data/spec/support/gridfs_tests/download_by_name.yml +113 -0
  214. data/spec/support/gridfs_tests/upload.yml +158 -0
  215. data/spec/support/sdam/rs/equal_electionids.yml +1 -2
  216. data/spec/support/sdam/rs/new_primary_new_electionid.yml +0 -3
  217. data/spec/support/sdam/rs/primary_mismatched_me.yml +37 -0
  218. data/spec/support/sdam/rs/primary_to_no_primary_mismatched_me.yml +75 -0
  219. data/spec/support/sdam/rs/secondary_mismatched_me.yml +37 -0
  220. data/spec/support/sdam/single/direct_connection_rsarbiter.yml +1 -1
  221. data/spec/support/sdam/single/direct_connection_rsprimary.yml +1 -1
  222. data/spec/support/sdam/single/direct_connection_rssecondary.yml +1 -1
  223. data/spec/support/sdam/single/direct_connection_slave.yml +1 -1
  224. data/spec/support/sdam/single/direct_connection_standalone.yml +1 -1
  225. data/spec/support/sdam/single/not_ok_response.yml +0 -1
  226. data/spec/support/server_discovery_and_monitoring.rb +3 -1
  227. data/spec/support/server_selection.rb +3 -1
  228. data/spec/support/shared/bulk_write.rb +192 -0
  229. data/spec/support/shared/server_selector.rb +21 -12
  230. metadata +147 -57
  231. metadata.gz.sig +0 -0
  232. data/lib/mongo/bulk_write/bulk_writable.rb +0 -252
  233. data/lib/mongo/bulk_write/deletable.rb +0 -57
  234. data/lib/mongo/bulk_write/insertable.rb +0 -49
  235. data/lib/mongo/bulk_write/replacable.rb +0 -58
  236. data/lib/mongo/bulk_write/updatable.rb +0 -69
  237. data/lib/mongo/grid/fs.rb +0 -146
  238. data/lib/mongo/operation/list_collections/result.rb +0 -114
  239. data/lib/mongo/operation/list_indexes/result.rb +0 -118
  240. data/lib/mongo/operation/read/collections_info.rb +0 -68
  241. data/lib/mongo/operation/read/indexes.rb +0 -69
  242. data/lib/mongo/operation/read/list_collections.rb +0 -76
  243. data/lib/mongo/operation/read/list_indexes.rb +0 -78
  244. data/lib/mongo/operation/write/bulk/bulk_delete.rb +0 -145
  245. data/lib/mongo/operation/write/bulk/bulk_delete/result.rb +0 -75
  246. data/lib/mongo/operation/write/bulk/bulk_insert.rb +0 -132
  247. data/lib/mongo/operation/write/bulk/bulk_insert/result.rb +0 -130
  248. data/lib/mongo/operation/write/bulk/bulk_mergable.rb +0 -67
  249. data/lib/mongo/operation/write/bulk/bulk_update.rb +0 -154
  250. data/lib/mongo/operation/write/bulk/bulk_update/result.rb +0 -174
  251. data/lib/mongo/operation/write/bulk/legacy_bulk_mergable.rb +0 -83
  252. data/spec/mongo/grid/fs_spec.rb +0 -160
  253. data/spec/mongo/loggable_spec.rb +0 -63
@@ -0,0 +1,64 @@
1
+ # Copyright (C) 2014-2015 MongoDB, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require 'mongo/grid/stream/read'
16
+ require 'mongo/grid/stream/write'
17
+
18
+ module Mongo
19
+ module Grid
20
+ class FSBucket
21
+
22
+ # A stream that reads and writes files from/to the FSBucket.
23
+ #
24
+ # @since 2.1.0
25
+ module Stream
26
+ extend self
27
+
28
+ # The symbol for opening a read stream.
29
+ #
30
+ # @since 2.1.0
31
+ READ_MODE = :r
32
+
33
+ # The symbol for opening a write stream.
34
+ #
35
+ # @since 2.1.0
36
+ WRITE_MODE = :w
37
+
38
+ # Mapping from mode to stream class.
39
+ #
40
+ # @since 2.1.0
41
+ MODE_MAP = {
42
+ READ_MODE => Read,
43
+ WRITE_MODE => Write
44
+ }.freeze
45
+
46
+ # Get a stream for reading/writing files from/to the FSBucket.
47
+ #
48
+ # @example Get a stream.
49
+ # FSBucket::Stream.get(fs, FSBucket::READ_MODE, options)
50
+ #
51
+ # @param [ FSBucket ] fs The GridFS bucket object.
52
+ # @param [ FSBucket::READ_MODE, FSBucket::WRITE_MODE ] mode The stream mode.
53
+ # @param [ Hash ] options The stream options.
54
+ #
55
+ # @return [ Stream::Read, Stream::Write ] The stream object.
56
+ #
57
+ # @since 2.1.0
58
+ def get(fs, mode, options = {})
59
+ MODE_MAP[mode].new(fs, options)
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,208 @@
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 Grid
17
+ class FSBucket
18
+
19
+ module Stream
20
+ # A stream that reads files from the FSBucket.
21
+ #
22
+ # @since 2.1.0
23
+ class Read
24
+ include Enumerable
25
+
26
+ # @return [ FSBucket ] fs The fs bucket from which this stream reads.
27
+ #
28
+ # @since 2.1.0
29
+ attr_reader :fs
30
+
31
+ # @return [ Hash ] options The stream options.
32
+ #
33
+ # @since 2.1.0
34
+ attr_reader :options
35
+
36
+ # @return [ BSON::ObjectId, Object ] file_id The id of the file being read.
37
+ #
38
+ # @since 2.1.0
39
+ attr_reader :file_id
40
+
41
+ # Create a stream for reading files from the FSBucket.
42
+ #
43
+ # @example Create the stream.
44
+ # Stream::Read.new(fs, options)
45
+ #
46
+ # @param [ FSBucket ] fs The GridFS bucket object.
47
+ # @param [ Hash ] options The read stream options.
48
+ #
49
+ # @since 2.1.0
50
+ def initialize(fs, options)
51
+ @fs = fs
52
+ @options = options.dup
53
+ @file_id = @options.delete(:file_id)
54
+ @open = true
55
+ end
56
+
57
+ # Iterate through chunk data streamed from the FSBucket.
58
+ #
59
+ # @example Iterate through the chunk data.
60
+ # stream.each do |data|
61
+ # buffer << data
62
+ # end
63
+ #
64
+ # @return [ Enumerator ] The enumerator.
65
+ #
66
+ # @raise [ Error::MissingFileChunk ] If a chunk is found out of sequence.
67
+ #
68
+ # @yieldparam [ Hash ] Each chunk of file data.
69
+ #
70
+ # @since 2.1.0
71
+ def each
72
+ ensure_readable!
73
+ num_chunks = (file_info.length + file_info.chunk_size - 1) / file_info.chunk_size
74
+ view.each_with_index.reduce(0) do |length_read, (doc, index)|
75
+ chunk = Grid::File::Chunk.new(doc)
76
+ validate!(index, num_chunks, chunk, length_read)
77
+ data = Grid::File::Chunk.assemble([ chunk ])
78
+ yield data
79
+ length_read += data.size
80
+ end if block_given?
81
+ view.to_enum
82
+ end
83
+
84
+ # Read all file data.
85
+ #
86
+ # @example Read the file data.
87
+ # stream.read
88
+ #
89
+ # @return [ String ] The file data.
90
+ #
91
+ # @raise [ Error::MissingFileChunk ] If a chunk is found out of sequence.
92
+ #
93
+ # @since 2.1.0
94
+ def read
95
+ to_a.join
96
+ end
97
+
98
+ # Close the read stream.
99
+ #
100
+ # @example Close the stream.
101
+ # stream.close
102
+ #
103
+ # @return [ BSON::ObjectId, Object ] The file id.
104
+ #
105
+ # @raise [ Error::ClosedStream ] If the stream is already closed.
106
+ #
107
+ # @since 2.1.0
108
+ def close
109
+ ensure_open!
110
+ view.close_query
111
+ @open = false
112
+ file_id
113
+ end
114
+
115
+ # Is the stream closed.
116
+ #
117
+ # @example Is the stream closd.
118
+ # stream.closed?
119
+ #
120
+ # @return [ true, false ] Whether the stream is closed.
121
+ #
122
+ # @since 2.1.0
123
+ def closed?
124
+ !@open
125
+ end
126
+
127
+ # Get the read preference used when streaming.
128
+ #
129
+ # @example Get the read preference.
130
+ # stream.read_preference
131
+ #
132
+ # @return [ Mongo::ServerSelector ] The read preference.
133
+ #
134
+ # @since 2.1.0
135
+ def read_preference
136
+ @read_preference ||= @options[:read] ?
137
+ ServerSelector.get((@options[:read] || {}).merge(fs.options)) :
138
+ fs.read_preference
139
+ end
140
+
141
+ # Get the files collection file information document for the file being read.
142
+ #
143
+ # @example Get the file info document.
144
+ # stream.file_info
145
+ #
146
+ # @return [ Hash ] The file info document.
147
+ #
148
+ # @since 2.1.0
149
+ def file_info
150
+ doc = fs.files_collection.find(_id: file_id).first
151
+ if doc
152
+ @file_info ||= File::Info.new(Options::Mapper.transform(doc, File::Info::MAPPINGS.invert))
153
+ end
154
+ end
155
+
156
+ private
157
+
158
+ def ensure_open!
159
+ raise Error::ClosedStream.new if closed?
160
+ end
161
+
162
+ def ensure_file_info!
163
+ raise Error::FileNotFound.new(file_id, :id) unless file_info
164
+ end
165
+
166
+ def ensure_readable!
167
+ ensure_open!
168
+ ensure_file_info!
169
+ end
170
+
171
+ def view
172
+ @view ||= fs.chunks_collection.find({ :files_id => file_id }, options).read(read_preference).sort(:n => 1)
173
+ end
174
+
175
+ def validate!(index, num_chunks, chunk, length_read)
176
+ validate_n!(index, chunk)
177
+ validate_length!(index, num_chunks, chunk, length_read)
178
+ end
179
+
180
+ def raise_unexpected_chunk_length!(chunk)
181
+ close
182
+ raise Error::UnexpectedChunkLength.new(file_info.chunk_size, chunk)
183
+ end
184
+
185
+ def validate_length!(index, num_chunks, chunk, length_read)
186
+ if num_chunks > 0 && chunk.data.data.size > 0
187
+ raise Error::ExtraFileChunk.new unless index < num_chunks
188
+ if index == num_chunks - 1
189
+ unless chunk.data.data.size + length_read == file_info.length
190
+ raise_unexpected_chunk_length!(chunk)
191
+ end
192
+ elsif chunk.data.data.size != file_info.chunk_size
193
+ raise_unexpected_chunk_length!(chunk)
194
+ end
195
+ end
196
+ end
197
+
198
+ def validate_n!(index, chunk)
199
+ unless index == chunk.n
200
+ close
201
+ raise Error::MissingFileChunk.new(index, chunk)
202
+ end
203
+ end
204
+ end
205
+ end
206
+ end
207
+ end
208
+ end
@@ -0,0 +1,187 @@
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 Grid
17
+ class FSBucket
18
+
19
+ module Stream
20
+ # A stream that writes files to the FSBucket.
21
+ #
22
+ # @since 2.1.0
23
+ class Write
24
+
25
+ # @return [ FSBucket ] fs The fs bucket to which this stream writes.
26
+ #
27
+ # @since 2.1.0
28
+ attr_reader :fs
29
+
30
+ # @return [ BSON::ObjectId ] file_id The id of the file being uploaded.
31
+ #
32
+ # @since 2.1.0
33
+ attr_reader :file_id
34
+
35
+ # @return [ String ] filename The name of the file being uploaded.
36
+ #
37
+ # @since 2.1.0
38
+ attr_reader :filename
39
+
40
+ # @return [ Hash ] options The write stream options.
41
+ #
42
+ # @since 2.1.0
43
+ attr_reader :options
44
+
45
+ # Create a stream for writing files to the FSBucket.
46
+ #
47
+ # @example Create the stream.
48
+ # Stream::Write.new(fs, options)
49
+ #
50
+ # @param [ FSBucket ] fs The GridFS bucket object.
51
+ # @param [ Hash ] options The write stream options.
52
+ #
53
+ # @option opts [ Integer ] :chunk_size Override the default chunk size.
54
+ # @option opts [ Hash ] :write The write concern.
55
+ # @option opts [ Hash ] :metadata User data for the 'metadata' field of the files collection document.
56
+ # @option opts [ String ] :content_type The content type of the file.
57
+ # Deprecated, please use the metadata document instead.
58
+ # @option opts [ Array<String> ] :aliases A list of aliases.
59
+ # Deprecated, please use the metadata document instead.
60
+ #
61
+ # @since 2.1.0
62
+ def initialize(fs, options)
63
+ @fs = fs
64
+ @length = 0
65
+ @n = 0
66
+ @file_id = BSON::ObjectId.new
67
+ @options = options
68
+ @filename = @options[:filename]
69
+ @open = true
70
+ end
71
+
72
+ # Write to the GridFS bucket from the source stream.
73
+ #
74
+ # @example Write to GridFS.
75
+ # stream.write(io)
76
+ #
77
+ # @param [ IO ] io The source io stream to upload from.
78
+ #
79
+ # @return [ Stream::Write ] self The write stream itself.
80
+ #
81
+ # @since 2.1.0
82
+ def write(io)
83
+ ensure_open!
84
+ @indexes ||= ensure_indexes!
85
+ data = io.read
86
+ @length += data.length
87
+ chunks = File::Chunk.split(data, file_info, @n)
88
+ @n += chunks.size
89
+ chunks_collection.insert_many(chunks) unless chunks.empty?
90
+ self
91
+ end
92
+
93
+ # Close the write stream.
94
+ #
95
+ # @example Close the stream.
96
+ # stream.close
97
+ #
98
+ # @return [ BSON::ObjectId, Object ] The file id.
99
+ #
100
+ # @raise [ Error::ClosedStream ] If the stream is already closed.
101
+ #
102
+ # @since 2.1.0
103
+ def close
104
+ ensure_open!
105
+ update_length
106
+ files_collection.insert_one(file_info)
107
+ @open = false
108
+ file_id
109
+ end
110
+
111
+ # Get the write concern used when uploading.
112
+ #
113
+ # @example Get the write concern.
114
+ # stream.write_concern
115
+ #
116
+ # @return [ Mongo::WriteConcern ] The write concern.
117
+ #
118
+ # @since 2.1.0
119
+ def write_concern
120
+ @write_concern ||= @options[:write] ? WriteConcern.get(@options[:write]) :
121
+ fs.write_concern
122
+ end
123
+
124
+ # Is the stream closed.
125
+ #
126
+ # @example Is the stream closed.
127
+ # stream.closed?
128
+ #
129
+ # @return [ true, false ] Whether the stream is closed.
130
+ #
131
+ # @since 2.1.0
132
+ def closed?
133
+ !@open
134
+ end
135
+
136
+ # Abort the upload by deleting all chunks already inserted.
137
+ #
138
+ # @example Abort the write operation.
139
+ # stream.abort
140
+ #
141
+ # @return [ true ] True if the operation was aborted and the stream is closed.
142
+ #
143
+ # @since 2.1.0
144
+ def abort
145
+ fs.chunks_collection.find(:files_id => file_id).delete_many
146
+ @open = false || true
147
+ end
148
+
149
+ private
150
+
151
+ def chunks_collection
152
+ with_write_concern(fs.chunks_collection)
153
+ end
154
+
155
+ def files_collection
156
+ with_write_concern(fs.files_collection)
157
+ end
158
+
159
+ def with_write_concern(collection)
160
+ if collection.write_concern.options == write_concern.options
161
+ collection
162
+ else
163
+ collection.client.with(write: write_concern.options)[collection.name]
164
+ end
165
+ end
166
+
167
+ def update_length
168
+ file_info.document[:length] = @length
169
+ end
170
+
171
+ def file_info
172
+ doc = { length: @length, _id: file_id, filename: filename }
173
+ @file_info ||= File::Info.new(options.merge(doc))
174
+ end
175
+
176
+ def ensure_indexes!
177
+ fs.send(:ensure_indexes!)
178
+ end
179
+
180
+ def ensure_open!
181
+ raise Error::ClosedStream.new if closed?
182
+ end
183
+ end
184
+ end
185
+ end
186
+ end
187
+ end