monga 0.0.6 → 0.0.7
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.
- data/README.md +5 -1
- data/benchmarks/inserts.rb +159 -54
- data/lib/monga/collection.rb +57 -1
- data/lib/monga/connection.rb +27 -17
- data/lib/monga/connections/buffer.rb +52 -38
- data/lib/monga/connections/em_connection.rb +2 -0
- data/lib/monga/connections/kgio_connection.rb +28 -18
- data/lib/monga/database.rb +71 -4
- data/lib/monga/protocol/delete.rb +1 -1
- data/lib/monga/protocol/insert.rb +3 -2
- data/lib/monga/protocol/query.rb +2 -2
- data/lib/monga/protocol/update.rb +2 -2
- data/lib/monga.rb +1 -8
- data/monga.gemspec +6 -5
- data/spec/helpers/mongodb.rb +7 -13
- data/spec/monga/block/collection_spec.rb +44 -0
- data/spec/monga/em/collection_spec.rb +70 -0
- data/spec/monga/sync/collection_spec.rb +56 -0
- data/spec/spec_helper.rb +2 -0
- metadata +10 -27
- data/lib/monga/connections/tcp_connection.rb +0 -59
data/README.md
CHANGED
@@ -143,7 +143,11 @@ puts "We have got #{docs.size} documents in this pretty array"
|
|
143
143
|
* [ ] check maxBsonSize / validate
|
144
144
|
* [x] cmd
|
145
145
|
* [x] eval
|
146
|
-
* [
|
146
|
+
* [x] aggregate
|
147
|
+
* [x] distinct
|
148
|
+
* [x] group
|
149
|
+
* [x] mapReduce
|
150
|
+
* [x] text
|
147
151
|
* [ ] gridfs?
|
148
152
|
|
149
153
|
### Collection
|
data/benchmarks/inserts.rb
CHANGED
@@ -1,86 +1,191 @@
|
|
1
1
|
require 'benchmark'
|
2
|
-
require 'mongo'
|
3
|
-
require 'moped'
|
4
|
-
require File.expand_path('../../lib/monga', __FILE__)
|
5
2
|
|
6
|
-
|
3
|
+
TOTAL_INSERTS = 10000
|
4
|
+
TOTAL_READS = 50
|
7
5
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
moped_session.use "dbTest"
|
6
|
+
chars = ('a'..'z').to_a
|
7
|
+
DOCS = [10, 100, 1000, 10000].map do |size|
|
8
|
+
doc = {}
|
9
|
+
doc[:title] = "Title"
|
10
|
+
doc[:body] = size.times.map{ chars.sample }.join
|
11
|
+
[size, doc]
|
12
|
+
end
|
16
13
|
|
17
|
-
|
18
|
-
document[:title] = "Some title"
|
19
|
-
chars = ('a'..'z').to_a
|
20
|
-
document[:body] = 100.times.map{ chars.sample } * ""
|
14
|
+
# Mongo Ruby Driver
|
21
15
|
|
22
|
-
|
16
|
+
fork do
|
17
|
+
require 'mongo'
|
18
|
+
include Mongo
|
23
19
|
|
24
|
-
|
20
|
+
Benchmark.bm do |x|
|
21
|
+
collection = MongoClient.new.db("dbTest").collection("testCollection")
|
25
22
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
23
|
+
DOCS.each do |size, doc|
|
24
|
+
GC.start
|
25
|
+
x.report("Mongo: Inserting #{size}b document") do
|
26
|
+
TOTAL_INSERTS.times do
|
27
|
+
collection.insert(doc.dup)
|
28
|
+
end
|
29
|
+
end
|
31
30
|
|
32
|
-
|
31
|
+
GC.start
|
32
|
+
x.report("Mongo: Reading #{size}b documents") do
|
33
|
+
TOTAL_READS.times do
|
34
|
+
collection.find.to_a
|
35
|
+
end
|
36
|
+
end
|
33
37
|
|
34
|
-
|
35
|
-
fetch.times do
|
36
|
-
mongo_collection.find.to_a
|
38
|
+
collection.drop
|
37
39
|
end
|
38
40
|
end
|
39
|
-
|
41
|
+
end
|
40
42
|
|
41
|
-
|
43
|
+
Process.waitall
|
44
|
+
puts "---"*5
|
42
45
|
|
43
|
-
|
46
|
+
# Monga Driver (blocking mode)
|
44
47
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
48
|
+
fork do
|
49
|
+
require File.expand_path('../../lib/monga', __FILE__)
|
50
|
+
|
51
|
+
Benchmark.bm do |x|
|
52
|
+
collection = Monga::Client.new.get_database("dbTest").get_collection("testCollection")
|
53
|
+
|
54
|
+
DOCS.each do |size, doc|
|
55
|
+
GC.start
|
56
|
+
x.report("Monga: Inserting #{size}b document") do
|
57
|
+
TOTAL_INSERTS.times do
|
58
|
+
collection.safe_insert(doc)
|
59
|
+
end
|
60
|
+
end
|
50
61
|
|
51
|
-
|
62
|
+
GC.start
|
63
|
+
x.report("Monga: Reading #{size}b documents") do
|
64
|
+
TOTAL_READS.times do
|
65
|
+
collection.find.all
|
66
|
+
end
|
67
|
+
end
|
52
68
|
|
53
|
-
|
54
|
-
fetch.times do
|
55
|
-
monga_collection.find.all
|
69
|
+
collection.drop
|
56
70
|
end
|
57
71
|
end
|
72
|
+
end
|
58
73
|
|
59
|
-
|
74
|
+
Process.waitall
|
75
|
+
puts "---"*5
|
60
76
|
|
61
|
-
|
77
|
+
# Moped
|
62
78
|
|
63
|
-
|
79
|
+
fork do
|
80
|
+
require 'moped'
|
64
81
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
82
|
+
Benchmark.bm do |x|
|
83
|
+
session = Moped::Session.new([ "127.0.0.1:27017" ])
|
84
|
+
session.use("dbTest")
|
85
|
+
|
86
|
+
DOCS.each do |size, doc|
|
87
|
+
GC.start
|
88
|
+
x.report("Moped: Inserting #{size}b document") do
|
89
|
+
session.with(safe: true) do |safe|
|
90
|
+
TOTAL_INSERTS.times do
|
91
|
+
safe[:testCollection].insert(doc)
|
92
|
+
end
|
93
|
+
end
|
69
94
|
end
|
70
|
-
end
|
71
|
-
end
|
72
95
|
|
73
|
-
|
96
|
+
GC.start
|
97
|
+
x.report("Moped: Reading #{size}b documents") do
|
98
|
+
TOTAL_READS.times do
|
99
|
+
session[:testCollection].find.to_a
|
100
|
+
end
|
101
|
+
end
|
74
102
|
|
75
|
-
|
76
|
-
fetch.times do
|
77
|
-
moped_session[:testCollection].find.to_a
|
103
|
+
session[:testCollection].drop
|
78
104
|
end
|
79
105
|
end
|
80
|
-
|
81
|
-
monga_collection.drop
|
82
106
|
end
|
83
107
|
|
108
|
+
Process.waitall
|
109
|
+
|
110
|
+
# # require 'moped'
|
111
|
+
|
112
|
+
# # include Mongo
|
113
|
+
|
114
|
+
# Benchmark.bm do |x|
|
115
|
+
# total = 1000
|
116
|
+
# fetch = 50
|
117
|
+
# # mongo_collection = MongoClient.new.db("dbTest").collection("testCollection")
|
118
|
+
# monga_collection = Monga::Client.new(type: :block).get_database("dbTest").get_collection("testCollection")
|
119
|
+
# Monga.logger.level = Logger::ERROR
|
120
|
+
# # moped_session = Moped::Session.new([ "127.0.0.1:27017" ])
|
121
|
+
# # moped_session.use "dbTest"
|
122
|
+
|
123
|
+
# document = {}
|
124
|
+
# document[:title] = "Some title"
|
125
|
+
# document[:body] = 10000.times.map{ chars.sample } * ""
|
126
|
+
|
127
|
+
# # sleep 0.5
|
128
|
+
|
129
|
+
# # GC.start
|
130
|
+
|
131
|
+
# # x.report("Inserting with mongo") do
|
132
|
+
# # total.times do |i|
|
133
|
+
# # mongo_collection.insert(document.dup)
|
134
|
+
# # end
|
135
|
+
# # end
|
136
|
+
|
137
|
+
# # GC.start
|
138
|
+
|
139
|
+
# # x.report("Fetching with mongo") do
|
140
|
+
# # fetch.times do
|
141
|
+
# # mongo_collection.find.to_a
|
142
|
+
# # end
|
143
|
+
# # end
|
144
|
+
# # mongo_collection.drop
|
145
|
+
|
146
|
+
# # sleep 0.5
|
147
|
+
|
148
|
+
# # GC.start
|
149
|
+
|
150
|
+
# x.report("Inserting with monga") do
|
151
|
+
# total.times do |i|
|
152
|
+
# monga_collection.safe_insert(document)
|
153
|
+
# end
|
154
|
+
# end
|
155
|
+
|
156
|
+
# GC.start
|
157
|
+
|
158
|
+
# x.report("Fetching with monga") do
|
159
|
+
# fetch.times do
|
160
|
+
# monga_collection.find.all
|
161
|
+
# end
|
162
|
+
# end
|
163
|
+
|
164
|
+
# monga_collection.drop
|
165
|
+
|
166
|
+
# # sleep 0.5
|
167
|
+
|
168
|
+
# # GC.start
|
169
|
+
|
170
|
+
# # x.report("Inserting with moped") do
|
171
|
+
# # moped_session.with(safe: true) do |safe|
|
172
|
+
# # total.times do |i|
|
173
|
+
# # safe[:testCollection].insert(document)
|
174
|
+
# # end
|
175
|
+
# # end
|
176
|
+
# # end
|
177
|
+
|
178
|
+
# # GC.start
|
179
|
+
|
180
|
+
# # x.report("Fetching with moped") do
|
181
|
+
# # fetch.times do
|
182
|
+
# # moped_session[:testCollection].find.to_a
|
183
|
+
# # end
|
184
|
+
# # end
|
185
|
+
|
186
|
+
# # monga_collection.drop
|
187
|
+
# end
|
188
|
+
|
84
189
|
|
85
190
|
|
86
191
|
|
data/lib/monga/collection.rb
CHANGED
@@ -8,7 +8,7 @@ module Monga
|
|
8
8
|
end
|
9
9
|
|
10
10
|
# Querying database. It returns cursor.
|
11
|
-
# Alias to collection#query is
|
11
|
+
# Alias to collection#query is collection#find
|
12
12
|
#
|
13
13
|
# cursor = collection.find(title: "Madonna")
|
14
14
|
# # choose fields to return
|
@@ -132,6 +132,62 @@ module Monga
|
|
132
132
|
end
|
133
133
|
end
|
134
134
|
|
135
|
+
def map_reduce(opts, &blk)
|
136
|
+
@db.map_reduce(@collection_name, opts) do |err, resp|
|
137
|
+
if block_given?
|
138
|
+
yield(err, resp)
|
139
|
+
else
|
140
|
+
raise err if err
|
141
|
+
return resp
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def aggregate(pipeline, &blk)
|
147
|
+
@db.aggregate(@collection_name, pipeline) do |err, resp|
|
148
|
+
if block_given?
|
149
|
+
yield(err, resp)
|
150
|
+
else
|
151
|
+
raise err if err
|
152
|
+
return resp
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
def distinct(opts, &blk)
|
158
|
+
@db.distinct(collection_name, opts) do |err, resp|
|
159
|
+
if block_given?
|
160
|
+
yield(err, resp)
|
161
|
+
else
|
162
|
+
raise err if err
|
163
|
+
return resp
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
def group(opts, &blk)
|
169
|
+
@db.group(collection_name, opts) do |err, resp|
|
170
|
+
if block_given?
|
171
|
+
yield(err, resp)
|
172
|
+
else
|
173
|
+
raise err if err
|
174
|
+
return resp
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
def text(search, opts = {}, &blk)
|
180
|
+
opts[:search] = search
|
181
|
+
@db.text(collection_name, opts) do |err, resp|
|
182
|
+
if block_given?
|
183
|
+
yield(err, resp)
|
184
|
+
else
|
185
|
+
raise err if err
|
186
|
+
return resp
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
135
191
|
# Safe methods
|
136
192
|
[:update, :insert, :delete, :remove, :ensure_index].each do |meth|
|
137
193
|
class_eval <<-EOS
|
data/lib/monga/connection.rb
CHANGED
@@ -6,17 +6,6 @@ module Monga
|
|
6
6
|
|
7
7
|
attr_reader :type
|
8
8
|
|
9
|
-
CONNECTIONS = {
|
10
|
-
em: Monga::Connections::EMConnection,
|
11
|
-
sync: Monga::Connections::FiberedConnection,
|
12
|
-
block: Monga::Connections::KGIOConnection,
|
13
|
-
}
|
14
|
-
PROXY_CONNECTIONS = {
|
15
|
-
em: Monga::Connections::EMProxyConnection,
|
16
|
-
sync: Monga::Connections::FiberedProxyConnection,
|
17
|
-
block: Monga::Connections::ProxyConnection,
|
18
|
-
}
|
19
|
-
|
20
9
|
# Simple connection wrapper.
|
21
10
|
# Accpets
|
22
11
|
# * host/port or server
|
@@ -35,15 +24,36 @@ module Monga
|
|
35
24
|
end
|
36
25
|
timeout = opts[:timeout]
|
37
26
|
|
38
|
-
|
39
|
-
|
40
|
-
|
27
|
+
@connection = case @type
|
28
|
+
when :em
|
29
|
+
require File.expand_path("../connections/em_connection", __FILE__)
|
30
|
+
Monga::Connections::EMConnection.connect(host, port, timeout)
|
31
|
+
when :sync
|
32
|
+
require File.expand_path("../connections/em_connection", __FILE__)
|
33
|
+
require File.expand_path("../connections/fibered_connection", __FILE__)
|
34
|
+
Monga::Connections::FiberedConnection.connect(host, port, timeout)
|
35
|
+
when :block
|
36
|
+
require File.expand_path("../connections/kgio_connection", __FILE__)
|
37
|
+
Monga::Connections::KGIOConnection.connect(host, port, timeout)
|
38
|
+
else
|
39
|
+
raise Monga::Exceptions::WrongConnectionType, "Connection type `#{opts[:type]}` is non valid, choose one of: :em, :sync, or :block" unless conn_type
|
40
|
+
end
|
41
41
|
end
|
42
|
-
|
42
|
+
|
43
43
|
# Returns name of proxy_connection class
|
44
44
|
def self.proxy_connection_class(type, client)
|
45
|
-
|
46
|
-
|
45
|
+
case type
|
46
|
+
when :em
|
47
|
+
require File.expand_path("../connections/em_proxy_connection", __FILE__)
|
48
|
+
Monga::Connections::EMProxyConnection.new(client)
|
49
|
+
when :sync
|
50
|
+
require File.expand_path("../connections/em_proxy_connection", __FILE__)
|
51
|
+
require File.expand_path("../connections/fibered_proxy_connection", __FILE__)
|
52
|
+
Monga::Connections::FiberedProxyConnection.new(client)
|
53
|
+
when :block
|
54
|
+
require File.expand_path("../connections/proxy_connection", __FILE__)
|
55
|
+
Monga::Connections::ProxyConnection.new(client)
|
56
|
+
end
|
47
57
|
end
|
48
58
|
end
|
49
59
|
end
|
@@ -1,33 +1,54 @@
|
|
1
1
|
module Monga::Connections
|
2
2
|
class Buffer
|
3
|
-
|
3
|
+
include Enumerable
|
4
|
+
EMPTY = ""
|
4
5
|
|
5
|
-
attr_reader :buffer, :
|
6
|
+
attr_reader :buffer, :buffer_size
|
6
7
|
|
7
8
|
def initialize
|
8
9
|
@buffer = ""
|
9
10
|
@position = 0
|
10
|
-
@
|
11
|
-
@
|
11
|
+
@buffer_size = 0
|
12
|
+
@response = []
|
12
13
|
end
|
13
14
|
|
14
15
|
def append(data)
|
15
16
|
@buffer << data
|
16
|
-
@buffer_size
|
17
|
-
|
18
|
-
|
17
|
+
@buffer_size += data.bytesize
|
18
|
+
end
|
19
|
+
|
20
|
+
def each
|
21
|
+
while doc = parse_buffer
|
22
|
+
yield doc
|
23
|
+
end
|
19
24
|
end
|
20
25
|
|
21
|
-
def
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
+
def parse_buffer
|
27
|
+
return if @buffer_size == 0
|
28
|
+
|
29
|
+
if @position == 0
|
30
|
+
parse_doc if parse_meta
|
31
|
+
else
|
32
|
+
parse_doc
|
33
|
+
end
|
34
|
+
|
35
|
+
if @number_returned == 0
|
36
|
+
if @buffer_size == @position
|
37
|
+
@buffer.clear
|
38
|
+
@buffer_size = 0
|
39
|
+
else
|
40
|
+
@buffer = @buffer[@position, @buffer_size-@position]
|
41
|
+
@buffer_size -= @position
|
42
|
+
end
|
43
|
+
@position = 0
|
44
|
+
|
45
|
+
@response
|
46
|
+
end
|
26
47
|
end
|
27
48
|
|
28
49
|
def parse_meta
|
29
50
|
return if @buffer_size < 36
|
30
|
-
@response
|
51
|
+
@response.clear
|
31
52
|
@response << ::BinUtils.get_int32_le(@buffer, @position)
|
32
53
|
@response << ::BinUtils.get_int32_le(@buffer, @position += 4)
|
33
54
|
@response << ::BinUtils.get_int32_le(@buffer, @position += 4)
|
@@ -35,43 +56,36 @@ module Monga::Connections
|
|
35
56
|
@response << ::BinUtils.get_int32_le(@buffer, @position += 4)
|
36
57
|
@response << ::BinUtils.get_int64_le(@buffer, @position += 4)
|
37
58
|
@response << ::BinUtils.get_int32_le(@buffer, @position += 8)
|
38
|
-
@
|
59
|
+
@number_returned = ::BinUtils.get_int32_le(@buffer, @position += 4)
|
60
|
+
@response << @number_returned
|
61
|
+
@position += 4
|
39
62
|
@response << []
|
40
63
|
|
41
|
-
@position += 4
|
42
64
|
end
|
43
65
|
|
44
66
|
def parse_doc
|
45
|
-
|
46
|
-
break if done
|
47
|
-
break if @buffer_size < @position + 4
|
48
|
-
doc_length = ::BinUtils.get_int32_le(@buffer, @position)
|
49
|
-
break if @buffer_size < @position + doc_length
|
67
|
+
@str_io = nil if @number_returned == @response[7]
|
50
68
|
|
51
|
-
|
52
|
-
|
53
|
-
@position
|
69
|
+
current_pos = @position
|
70
|
+
while (l = @buffer_size - @position) > 4
|
71
|
+
doc_length = ::BinUtils.get_int32_le(@buffer, @position)
|
72
|
+
break if l < doc_length
|
54
73
|
@number_returned -= 1
|
74
|
+
@position += doc_length
|
55
75
|
end
|
56
|
-
end
|
57
76
|
|
58
|
-
|
59
|
-
|
60
|
-
|
77
|
+
if @str_io
|
78
|
+
@str_io << @buffer[current_pos..@position]
|
79
|
+
else
|
80
|
+
@str_io = StringIO.new @buffer[current_pos..@position]
|
61
81
|
end
|
62
|
-
end
|
63
82
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
@buffer.clear
|
70
|
-
else
|
71
|
-
@buffer = @buffer[@position, @buffer_size-@position]
|
83
|
+
if @number_returned == 0
|
84
|
+
@str_io.rewind
|
85
|
+
@response[7].times do
|
86
|
+
@response[-1] << BSON::Document.from_bson(@str_io)
|
87
|
+
end
|
72
88
|
end
|
73
|
-
@buffer_size = @buffer.bytesize
|
74
|
-
@position = 0
|
75
89
|
end
|
76
90
|
end
|
77
91
|
end
|
@@ -1,7 +1,10 @@
|
|
1
1
|
require 'kgio'
|
2
|
-
|
2
|
+
|
3
|
+
# Toy blocking connection over TCP
|
3
4
|
module Monga::Connections
|
4
5
|
class KGIOConnection
|
6
|
+
TO_RECV = 512
|
7
|
+
|
5
8
|
def self.connect(host, port, timeout)
|
6
9
|
new(host, port, timeout)
|
7
10
|
end
|
@@ -10,6 +13,7 @@ module Monga::Connections
|
|
10
13
|
@host, @port, @timout = host, port, timeout
|
11
14
|
@connected = true
|
12
15
|
@buffer = Buffer.new
|
16
|
+
@tmp = ""
|
13
17
|
end
|
14
18
|
|
15
19
|
def connected?
|
@@ -20,10 +24,10 @@ module Monga::Connections
|
|
20
24
|
def socket
|
21
25
|
@socket ||= begin
|
22
26
|
sock = Kgio::TCPSocket.new(@host, @port)
|
27
|
+
# MacOS doesn't support autopush
|
23
28
|
sock.kgio_autopush = true unless RUBY_PLATFORM['darwin']
|
24
29
|
# check connection
|
25
30
|
sock.kgio_write ""
|
26
|
-
# Macos doesn't support autopush
|
27
31
|
@connected = true
|
28
32
|
sock
|
29
33
|
end
|
@@ -31,18 +35,19 @@ module Monga::Connections
|
|
31
35
|
nil
|
32
36
|
end
|
33
37
|
|
34
|
-
# Fake answer, as far as we are blocking
|
38
|
+
# Fake answer, as far as we are blocking,
|
39
|
+
# but we should support API
|
35
40
|
def responses
|
36
41
|
0
|
37
42
|
end
|
38
43
|
|
39
44
|
def send_command(msg, request_id=nil, &cb)
|
40
45
|
raise Errno::ECONNREFUSED, "Connection Refused" unless socket
|
41
|
-
socket.kgio_write msg
|
46
|
+
socket.kgio_write msg
|
42
47
|
if cb
|
43
48
|
read_socket
|
44
49
|
|
45
|
-
message = @buffer.
|
50
|
+
message = @buffer.first
|
46
51
|
rid = message[2]
|
47
52
|
|
48
53
|
fail "Returned Request Id is not equal to sended one (#{rid} != #{request_id}), #{message}" if rid != request_id
|
@@ -58,19 +63,24 @@ module Monga::Connections
|
|
58
63
|
end
|
59
64
|
|
60
65
|
def read_socket
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
size
|
70
|
-
|
71
|
-
|
66
|
+
while @buffer.buffer_size < 4
|
67
|
+
unless socket.kgio_read(TO_RECV, @tmp)
|
68
|
+
raise Errno::ECONNREFUSED.new "Nil was return. Closing connection"
|
69
|
+
end
|
70
|
+
|
71
|
+
@buffer.append(@tmp)
|
72
|
+
|
73
|
+
size = @buffer.buffer_size
|
74
|
+
if size >= 4
|
75
|
+
length = ::BinUtils.get_int32_le(@buffer.buffer)
|
76
|
+
|
77
|
+
torecv = length - size
|
78
|
+
if torecv > 0
|
79
|
+
socket.read(torecv, @tmp)
|
80
|
+
@buffer.append(@tmp)
|
81
|
+
end
|
82
|
+
end
|
72
83
|
end
|
73
|
-
@buffer.append(buf)
|
74
84
|
end
|
75
85
|
|
76
86
|
def primary?
|
@@ -83,7 +93,7 @@ module Monga::Connections
|
|
83
93
|
request_id = req.request_id
|
84
94
|
socket.kgio_write command
|
85
95
|
read_socket
|
86
|
-
message = @buffer.
|
96
|
+
message = @buffer.first
|
87
97
|
@primary = message.last.first["ismaster"]
|
88
98
|
yield @primary ? :primary : :secondary
|
89
99
|
rescue => e
|
data/lib/monga/database.rb
CHANGED
@@ -146,12 +146,79 @@ module Monga
|
|
146
146
|
run_cmd(cmd, blk)
|
147
147
|
end
|
148
148
|
|
149
|
-
|
150
|
-
|
149
|
+
# Run mapReduce command.
|
150
|
+
# Available options:
|
151
|
+
#
|
152
|
+
# * map - A JavaScript function that associates or “maps” a value with a key and emits the key and value pair.
|
153
|
+
# * reduce - A JavaScript function that “reduces” to a single object all the values associated with a particular key.
|
154
|
+
# * out - Specifies the location of the result of the map-reduce operation.
|
155
|
+
# * query - Specifies the selection criteria.
|
156
|
+
# * sort - Sorts the input documents.
|
157
|
+
# * limit - Specifies a maximum number of documents to return from the collection
|
158
|
+
# * finalize
|
159
|
+
# * scope
|
160
|
+
# * jsMode
|
161
|
+
# * verbose
|
162
|
+
#
|
163
|
+
# Inline response returned by default.
|
164
|
+
#
|
165
|
+
def map_reduce(collection_name, opts, &blk)
|
166
|
+
cmd = {}
|
167
|
+
cmd[:mapReduce] = collection_name
|
168
|
+
cmd.merge! opts
|
169
|
+
cmd[:out] ||= { inline: 1 }
|
170
|
+
run_cmd(cmd, blk)
|
151
171
|
end
|
152
172
|
|
153
|
-
|
154
|
-
|
173
|
+
# Run aggregate command.
|
174
|
+
#
|
175
|
+
def aggregate(collection_name, pipeline, &blk)
|
176
|
+
cmd = {}
|
177
|
+
cmd[:aggregate] = collection_name
|
178
|
+
cmd[:pipeline] = pipeline
|
179
|
+
run_cmd(cmd, blk)
|
180
|
+
end
|
181
|
+
|
182
|
+
# Run distinct command.
|
183
|
+
# You should pass collection_name and key.
|
184
|
+
# Query option is optional.
|
185
|
+
#
|
186
|
+
def distinct(collection_name, opts, &blk)
|
187
|
+
cmd = {}
|
188
|
+
cmd[:distinct] = collection_name
|
189
|
+
cmd.merge! opts
|
190
|
+
run_cmd(cmd, blk)
|
191
|
+
end
|
192
|
+
|
193
|
+
# Run group command.
|
194
|
+
# Available options are:
|
195
|
+
# key – Specifies one or more document fields to group
|
196
|
+
# $reduce – Specifies an aggregation function that operates on the documents during the grouping operation
|
197
|
+
# initial – Initializes the aggregation result document
|
198
|
+
# $keyf – Specifies a function that creates a “key object” for use as the grouping key
|
199
|
+
# cond – Specifies the selection criteria to determine which documents in the collection to process
|
200
|
+
# finalize – Specifies a function that runs each item in the result
|
201
|
+
#
|
202
|
+
def group(collection_name, opts, &blk)
|
203
|
+
cmd = {}
|
204
|
+
cmd[:group] = opts
|
205
|
+
cmd[:group][:ns] ||= collection_name
|
206
|
+
run_cmd(cmd, blk)
|
207
|
+
end
|
208
|
+
|
209
|
+
# Run text command.
|
210
|
+
# Available options are:
|
211
|
+
# search (string) – A string of terms that MongoDB parses and uses to query the text index
|
212
|
+
# filter (document) – A query document to further limit the results of the query using another database field
|
213
|
+
# project (document) – Allows you to limit the fields returned by the query to only those specified.
|
214
|
+
# limit (number) – Specify the maximum number of documents to include in the response
|
215
|
+
# language (string) – Specify the language that determines for the search the list of stop words and the rules for the stemmer and tokenizer
|
216
|
+
#
|
217
|
+
def text(collection_name, opts, &blk)
|
218
|
+
cmd = {}
|
219
|
+
cmd[:text] = collection_name
|
220
|
+
cmd.merge! opts
|
221
|
+
run_cmd(cmd, blk)
|
155
222
|
end
|
156
223
|
|
157
224
|
# Just helper to show all list of collections
|
@@ -15,10 +15,11 @@ module Monga::Protocol
|
|
15
15
|
case documents
|
16
16
|
when Array
|
17
17
|
documents.each do |doc|
|
18
|
-
msg <<
|
18
|
+
msg << doc.to_bson
|
19
19
|
end
|
20
20
|
when Hash
|
21
|
-
msg << BSON::BSON_C.serialize(documents).to_s
|
21
|
+
# msg << BSON::BSON_C.serialize(documents).to_s
|
22
|
+
msg << documents.to_bson
|
22
23
|
end
|
23
24
|
msg
|
24
25
|
end
|
data/lib/monga/protocol/query.rb
CHANGED
@@ -26,8 +26,8 @@ module Monga::Protocol
|
|
26
26
|
msg = ::BinUtils.append_int32_le!(nil, flags)
|
27
27
|
msg << full_name << Monga::NULL_BYTE
|
28
28
|
::BinUtils.append_int32_le!(msg, skip, limit)
|
29
|
-
msg <<
|
30
|
-
msg <<
|
29
|
+
msg << query.to_bson
|
30
|
+
msg << selector.to_bson if selector.any?
|
31
31
|
msg
|
32
32
|
end
|
33
33
|
end
|
@@ -15,8 +15,8 @@ module Monga::Protocol
|
|
15
15
|
msg = ::BinUtils.append_int32_le!(nil, 0)
|
16
16
|
msg << full_name << Monga::NULL_BYTE
|
17
17
|
::BinUtils.append_int32_le!(msg, flags)
|
18
|
-
msg <<
|
19
|
-
msg <<
|
18
|
+
msg << query.to_bson
|
19
|
+
msg << update.to_bson
|
20
20
|
msg
|
21
21
|
end
|
22
22
|
end
|
data/lib/monga.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
gem "bson", "2.0.0.beta"
|
2
2
|
require "bson"
|
3
3
|
require "bin_utils"
|
4
4
|
require "logger"
|
@@ -21,13 +21,6 @@ require File.expand_path("../monga/cursor", __FILE__)
|
|
21
21
|
|
22
22
|
require File.expand_path("../monga/clients/single_instance_client", __FILE__)
|
23
23
|
require File.expand_path("../monga/clients/replica_set_client", __FILE__)
|
24
|
-
require File.expand_path("../monga/connections/em_connection", __FILE__)
|
25
|
-
require File.expand_path("../monga/connections/fibered_connection", __FILE__)
|
26
|
-
require File.expand_path("../monga/connections/tcp_connection", __FILE__)
|
27
|
-
require File.expand_path("../monga/connections/kgio_connection", __FILE__)
|
28
|
-
require File.expand_path("../monga/connections/em_proxy_connection", __FILE__)
|
29
|
-
require File.expand_path("../monga/connections/fibered_proxy_connection", __FILE__)
|
30
|
-
require File.expand_path("../monga/connections/proxy_connection", __FILE__)
|
31
24
|
require File.expand_path("../monga/connections/buffer", __FILE__)
|
32
25
|
|
33
26
|
require File.expand_path("../monga/client", __FILE__)
|
data/monga.gemspec
CHANGED
@@ -4,11 +4,11 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
4
|
|
5
5
|
Gem::Specification.new do |spec|
|
6
6
|
spec.name = "monga"
|
7
|
-
spec.version = "0.0.
|
7
|
+
spec.version = "0.0.7"
|
8
8
|
spec.authors = ["Petr Yanovich"]
|
9
9
|
spec.email = ["fl00r@yandex.ru"]
|
10
|
-
spec.description = %q{MongoDB Ruby
|
11
|
-
spec.summary = %q{MongoDB Ruby
|
10
|
+
spec.description = %q{Yet another MongoDB Ruby Client}
|
11
|
+
spec.summary = %q{Yet another MongoDB Ruby Client}
|
12
12
|
spec.homepage = ""
|
13
13
|
spec.license = "MIT"
|
14
14
|
|
@@ -22,7 +22,8 @@ Gem::Specification.new do |spec|
|
|
22
22
|
spec.add_development_dependency "kgio"
|
23
23
|
spec.add_development_dependency "em-synchrony"
|
24
24
|
|
25
|
-
spec.add_dependency "bson"
|
26
|
-
spec.add_dependency "
|
25
|
+
spec.add_dependency "bson", ["~> 2.0.0.beta"]
|
26
|
+
# spec.add_dependency "bson"
|
27
|
+
# spec.add_dependency "bson_ext"
|
27
28
|
spec.add_dependency "bin_utils"
|
28
29
|
end
|
data/spec/helpers/mongodb.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
|
-
|
1
|
+
require 'eventmachine'
|
2
2
|
|
3
|
+
module Fake
|
3
4
|
# Fake Response.
|
4
5
|
# It could be `ok`, or `primary?` reply.
|
5
6
|
class Response
|
@@ -11,12 +12,10 @@ module Fake
|
|
11
12
|
def ok(doc = nil)
|
12
13
|
document = doc || { ok: 1.0 }
|
13
14
|
[flags, cursor_id, starting_from, number_returned].pack("LQLL")
|
14
|
-
b =
|
15
|
-
|
16
|
-
|
17
|
-
b.
|
18
|
-
b.put_int(number_returned)
|
19
|
-
b.append!(BSON::BSON_C.serialize(document).to_s)
|
15
|
+
b = ::BinUtils.append_int32_le!(nil, flags)
|
16
|
+
::BinUtils.append_int64_le!(b, cursor_id)
|
17
|
+
::BinUtils.append_int32_le!(b, starting_from, number_returned)
|
18
|
+
b << document.to_bson
|
20
19
|
|
21
20
|
header(b) + b.to_s
|
22
21
|
end
|
@@ -33,12 +32,7 @@ module Fake
|
|
33
32
|
request_id = 0
|
34
33
|
op_code = 0
|
35
34
|
|
36
|
-
h =
|
37
|
-
h.put_int(length)
|
38
|
-
h.put_int(request_id)
|
39
|
-
h.put_int(response_to)
|
40
|
-
h.put_int(op_code)
|
41
|
-
h.to_s
|
35
|
+
h = ::BinUtils.append_int32_le!(nil, flags, request_id, response_to, op_code)
|
42
36
|
end
|
43
37
|
|
44
38
|
def response_to
|
@@ -169,4 +169,48 @@ describe Monga::Collection do
|
|
169
169
|
docs.select{ |d| d["ns"] == "dbTest.testCollection" }.size.must_equal 1
|
170
170
|
end
|
171
171
|
end
|
172
|
+
|
173
|
+
# MAP/REDUCE
|
174
|
+
|
175
|
+
describe "map_reduce" do
|
176
|
+
before do
|
177
|
+
@collection.safe_remove
|
178
|
+
5.times do |i|
|
179
|
+
@collection.safe_insert(title: "The Book", count: i)
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
it "should run map reduce" do
|
184
|
+
map_func = "function() {
|
185
|
+
emit(this.title, this.count);
|
186
|
+
};"
|
187
|
+
red_func = "function(docTitle, docCount) {
|
188
|
+
return Array.sum(docCount);
|
189
|
+
};"
|
190
|
+
@collection.map_reduce(map: map_func, reduce: red_func, out: {inline: 1} )["results"].first["value"].must_equal 10.0
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
# AGGREGATE, GROUP, DISTINCT
|
195
|
+
|
196
|
+
describe "aggregate, group, distinct" do
|
197
|
+
|
198
|
+
end
|
199
|
+
|
200
|
+
# TEXT SEARCH
|
201
|
+
|
202
|
+
# Travis.ci doesn't support text search in mongodb
|
203
|
+
# describe "text search" do
|
204
|
+
# before do
|
205
|
+
# @collection.safe_ensure_index(author: "text")
|
206
|
+
# @collection.safe_insert(author: "Lady Gaga", track: "No. 1")
|
207
|
+
# @collection.safe_insert(author: "Lady Gaga", track: "No. 2")
|
208
|
+
# @collection.safe_insert(author: "Madonna", track: "No. 1")
|
209
|
+
# end
|
210
|
+
|
211
|
+
# it "should find some tracks" do
|
212
|
+
# @collection.text("Lady")["results"].map{ |r| r["obj"]["track"] }.sort.must_equal ["No. 1", "No. 2"]
|
213
|
+
# @collection.text("Madonna")["results"].map{ |r| r["obj"]["track"] }.sort.must_equal ["No. 1"]
|
214
|
+
# end
|
215
|
+
# end
|
172
216
|
end
|
@@ -305,4 +305,74 @@ describe Monga::Collection do
|
|
305
305
|
end
|
306
306
|
end
|
307
307
|
end
|
308
|
+
|
309
|
+
# MAP/REDUCE
|
310
|
+
|
311
|
+
describe "map_reduce" do
|
312
|
+
before do
|
313
|
+
EM.run do
|
314
|
+
@collection.safe_remove do
|
315
|
+
docs = []
|
316
|
+
5.times do |i|
|
317
|
+
docs << { title: "The Book", count: i }
|
318
|
+
end
|
319
|
+
@collection.safe_insert(docs) do
|
320
|
+
EM.stop
|
321
|
+
end
|
322
|
+
end
|
323
|
+
end
|
324
|
+
end
|
325
|
+
|
326
|
+
it "should run map reduce" do
|
327
|
+
EM.run do
|
328
|
+
map_func = "function() {
|
329
|
+
emit(this.title, this.count);
|
330
|
+
};"
|
331
|
+
red_func = "function(docTitle, docCount) {
|
332
|
+
return Array.sum(docCount);
|
333
|
+
};"
|
334
|
+
@collection.map_reduce(map: map_func, reduce: red_func, out: {inline: 1} ) do |err, res|
|
335
|
+
res["results"].first["value"].must_equal 10.0
|
336
|
+
EM.stop
|
337
|
+
end
|
338
|
+
end
|
339
|
+
end
|
340
|
+
end
|
341
|
+
|
342
|
+
# AGGREGATE, GROUP, DISTINCT
|
343
|
+
|
344
|
+
describe "aggregate, group, distinct" do
|
345
|
+
|
346
|
+
end
|
347
|
+
|
348
|
+
# TEXT SEARCH
|
349
|
+
|
350
|
+
# Travis.ci doesn't support text search in mongodb
|
351
|
+
# describe "text search" do
|
352
|
+
# before do
|
353
|
+
# EM.run do
|
354
|
+
# @collection.safe_ensure_index(author: "text") do
|
355
|
+
# @collection.safe_insert([
|
356
|
+
# { author: "Lady Gaga", track: "No. 1" },
|
357
|
+
# { author: "Lady Gaga", track: "No. 2" },
|
358
|
+
# { author: "Madonna", track: "No. 1" }
|
359
|
+
# ]) do
|
360
|
+
# EM.stop
|
361
|
+
# end
|
362
|
+
# end
|
363
|
+
# end
|
364
|
+
# end
|
365
|
+
|
366
|
+
# it "should find some tracks" do
|
367
|
+
# EM.run do
|
368
|
+
# @collection.text("Lady") do |err, res|
|
369
|
+
# res["results"].map{ |r| r["obj"]["track"] }.sort.must_equal ["No. 1", "No. 2"]
|
370
|
+
# @collection.text("Madonna") do |err, res|
|
371
|
+
# res["results"].map{ |r| r["obj"]["track"] }.sort.must_equal ["No. 1"]
|
372
|
+
# EM.stop
|
373
|
+
# end
|
374
|
+
# end
|
375
|
+
# end
|
376
|
+
# end
|
377
|
+
# end
|
308
378
|
end
|
@@ -244,4 +244,60 @@ describe Monga::Collection do
|
|
244
244
|
end
|
245
245
|
end
|
246
246
|
end
|
247
|
+
|
248
|
+
# MAP/REDUCE
|
249
|
+
|
250
|
+
describe "map_reduce" do
|
251
|
+
before do
|
252
|
+
EM.synchrony do
|
253
|
+
@collection.safe_remove
|
254
|
+
5.times do |i|
|
255
|
+
@collection.safe_insert(title: "The Book", count: i)
|
256
|
+
end
|
257
|
+
EM.stop
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
it "should run map reduce" do
|
262
|
+
EM.synchrony do
|
263
|
+
map_func = "function() {
|
264
|
+
emit(this.title, this.count);
|
265
|
+
};"
|
266
|
+
red_func = "function(docTitle, docCount) {
|
267
|
+
return Array.sum(docCount);
|
268
|
+
};"
|
269
|
+
@collection.map_reduce(map: map_func, reduce: red_func, out: {inline: 1} )["results"].first["value"].must_equal 10.0
|
270
|
+
EM.stop
|
271
|
+
end
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
# AGGREGATE, GROUP, DISTINCT
|
276
|
+
|
277
|
+
describe "aggregate, group, distinct" do
|
278
|
+
|
279
|
+
end
|
280
|
+
|
281
|
+
# TEXT SEARCH
|
282
|
+
|
283
|
+
# Travis.ci doesn't support text search in mongodb
|
284
|
+
# describe "text search" do
|
285
|
+
# before do
|
286
|
+
# EM.synchrony do
|
287
|
+
# @collection.safe_ensure_index(author: "text")
|
288
|
+
# @collection.safe_insert(author: "Lady Gaga", track: "No. 1")
|
289
|
+
# @collection.safe_insert(author: "Lady Gaga", track: "No. 2")
|
290
|
+
# @collection.safe_insert(author: "Madonna", track: "No. 1")
|
291
|
+
# EM.stop
|
292
|
+
# end
|
293
|
+
# end
|
294
|
+
|
295
|
+
# it "should find some tracks" do
|
296
|
+
# EM.synchrony do
|
297
|
+
# @collection.text("Lady")["results"].map{ |r| r["obj"]["track"] }.sort.must_equal ["No. 1", "No. 2"]
|
298
|
+
# @collection.text("Madonna")["results"].map{ |r| r["obj"]["track"] }.sort.must_equal ["No. 1"]
|
299
|
+
# EM.stop
|
300
|
+
# end
|
301
|
+
# end
|
302
|
+
# end
|
247
303
|
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: monga
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.7
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-05-29 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
@@ -78,35 +78,19 @@ dependencies:
|
|
78
78
|
- !ruby/object:Gem::Dependency
|
79
79
|
requirement: !ruby/object:Gem::Requirement
|
80
80
|
requirements:
|
81
|
-
- -
|
81
|
+
- - ~>
|
82
82
|
- !ruby/object:Gem::Version
|
83
|
-
version:
|
83
|
+
version: 2.0.0.beta
|
84
84
|
none: false
|
85
85
|
type: :runtime
|
86
86
|
version_requirements: !ruby/object:Gem::Requirement
|
87
87
|
requirements:
|
88
|
-
- -
|
88
|
+
- - ~>
|
89
89
|
- !ruby/object:Gem::Version
|
90
|
-
version:
|
90
|
+
version: 2.0.0.beta
|
91
91
|
none: false
|
92
92
|
prerelease: false
|
93
93
|
name: bson
|
94
|
-
- !ruby/object:Gem::Dependency
|
95
|
-
requirement: !ruby/object:Gem::Requirement
|
96
|
-
requirements:
|
97
|
-
- - ! '>='
|
98
|
-
- !ruby/object:Gem::Version
|
99
|
-
version: '0'
|
100
|
-
none: false
|
101
|
-
type: :runtime
|
102
|
-
version_requirements: !ruby/object:Gem::Requirement
|
103
|
-
requirements:
|
104
|
-
- - ! '>='
|
105
|
-
- !ruby/object:Gem::Version
|
106
|
-
version: '0'
|
107
|
-
none: false
|
108
|
-
prerelease: false
|
109
|
-
name: bson_ext
|
110
94
|
- !ruby/object:Gem::Dependency
|
111
95
|
requirement: !ruby/object:Gem::Requirement
|
112
96
|
requirements:
|
@@ -123,7 +107,7 @@ dependencies:
|
|
123
107
|
none: false
|
124
108
|
prerelease: false
|
125
109
|
name: bin_utils
|
126
|
-
description: MongoDB Ruby
|
110
|
+
description: Yet another MongoDB Ruby Client
|
127
111
|
email:
|
128
112
|
- fl00r@yandex.ru
|
129
113
|
executables: []
|
@@ -153,7 +137,6 @@ files:
|
|
153
137
|
- lib/monga/connections/fibered_proxy_connection.rb
|
154
138
|
- lib/monga/connections/kgio_connection.rb
|
155
139
|
- lib/monga/connections/proxy_connection.rb
|
156
|
-
- lib/monga/connections/tcp_connection.rb
|
157
140
|
- lib/monga/cursor.rb
|
158
141
|
- lib/monga/database.rb
|
159
142
|
- lib/monga/protocol/delete.rb
|
@@ -194,7 +177,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
194
177
|
requirements:
|
195
178
|
- - ! '>='
|
196
179
|
- !ruby/object:Gem::Version
|
197
|
-
hash: -
|
180
|
+
hash: -862637376897312253
|
198
181
|
version: '0'
|
199
182
|
segments:
|
200
183
|
- 0
|
@@ -203,7 +186,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
203
186
|
requirements:
|
204
187
|
- - ! '>='
|
205
188
|
- !ruby/object:Gem::Version
|
206
|
-
hash: -
|
189
|
+
hash: -862637376897312253
|
207
190
|
version: '0'
|
208
191
|
segments:
|
209
192
|
- 0
|
@@ -213,7 +196,7 @@ rubyforge_project:
|
|
213
196
|
rubygems_version: 1.8.25
|
214
197
|
signing_key:
|
215
198
|
specification_version: 3
|
216
|
-
summary: MongoDB Ruby
|
199
|
+
summary: Yet another MongoDB Ruby Client
|
217
200
|
test_files:
|
218
201
|
- spec/helpers/mongodb.rb
|
219
202
|
- spec/monga/block/collection_spec.rb
|
@@ -1,59 +0,0 @@
|
|
1
|
-
require 'socket'
|
2
|
-
|
3
|
-
# Currently blocking mode is very poor.
|
4
|
-
# It is working as is.
|
5
|
-
# Going to support reconnecting and timouts later.
|
6
|
-
# Use it for tests and prototyping. Not the best choice for production.
|
7
|
-
|
8
|
-
module Monga::Connections
|
9
|
-
class TCPConnection
|
10
|
-
def self.connect(host, port, timeout)
|
11
|
-
new(host, port, timeout)
|
12
|
-
end
|
13
|
-
|
14
|
-
def initialize(host, port, timeout)
|
15
|
-
@host, @port, @timout = host, port, timeout
|
16
|
-
@connected = true
|
17
|
-
@buffer = Buffer.new
|
18
|
-
end
|
19
|
-
|
20
|
-
def connected?
|
21
|
-
@connected
|
22
|
-
end
|
23
|
-
|
24
|
-
def socket
|
25
|
-
@socket ||= begin
|
26
|
-
TCPSocket.new(@host, @port)
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
# Fake answer, as far as we are blocking
|
31
|
-
def responses
|
32
|
-
0
|
33
|
-
end
|
34
|
-
|
35
|
-
def send_command(msg, request_id=nil, &cb)
|
36
|
-
socket.send msg.to_s, 0
|
37
|
-
if cb
|
38
|
-
length = socket.read(4)
|
39
|
-
raise Errno::ECONNREFUSED, "Socket returns nothing like it would be closed." unless length
|
40
|
-
@buffer.append(length)
|
41
|
-
l = length.unpack("L").first
|
42
|
-
rest = socket.read(l-4)
|
43
|
-
@buffer.append(rest)
|
44
|
-
@buffer.each do |message|
|
45
|
-
rid = message[2]
|
46
|
-
fail "Returned Request Id is not equal to sended one" if rid != request_id
|
47
|
-
cb.call(message)
|
48
|
-
end
|
49
|
-
end
|
50
|
-
rescue Errno::ECONNREFUSED, Errno::EPIPE => e
|
51
|
-
@connected = false
|
52
|
-
@socket = nil
|
53
|
-
if cb
|
54
|
-
err = Monga::Exceptions::Disconnected.new("Disconnected from #{@host}:#{@port}, #{e.message}")
|
55
|
-
cb.call(err)
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|