Module: Tarantool16::Connection::Common

Included in:
Dumb
Defined in:
lib/tarantool16/connection/common.rb

Constant Summary collapse

DEFAULT_RECONNECT =
0.2
CLOCK_KIND =
::Process::CLOCK_REALTIME
REQ_EMPTY =
{}.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#hostObject (readonly)

Returns the value of attribute host.



19
20
21
# File 'lib/tarantool16/connection/common.rb', line 19

def host
  @host
end

Instance Method Details

#_call(name, args, cb) ⇒ Object



217
218
219
220
221
# File 'lib/tarantool16/connection/common.rb', line 217

def _call(name, args, cb)
  req = {IPROTO_FUNCTION_NAME => name,
         IPROTO_TUPLE => args}
  send_request(REQUEST_TYPE_CALL, req, cb)
end

#_delete(space_no, index_no, key, cb) ⇒ Object



180
181
182
183
184
185
# File 'lib/tarantool16/connection/common.rb', line 180

def _delete(space_no, index_no, key, cb)
  req = {IPROTO_SPACE_ID => space_no,
         IPROTO_INDEX_ID => index_no,
         IPROTO_KEY => key}
  send_request(REQUEST_TYPE_DELETE, req, cb)
end

#_eval(expr, args, cb) ⇒ Object



223
224
225
226
227
# File 'lib/tarantool16/connection/common.rb', line 223

def _eval(expr, args, cb)
  req = {IPROTO_EXPR => expr,
         IPROTO_TUPLE => args}
  send_request(REQUEST_TYPE_EVAL, req, cb)
end

#_init_common(host, opts) ⇒ Object



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/tarantool16/connection/common.rb', line 20

def _init_common(host, opts)
  @host = host
  @user = opts[:user]
  if opts[:password]
    @passwd = ::OpenSSL::Digest::SHA1.digest(opts[:password])
  end
  if opts[:reconnect].nil?
    @reconnect_timeout = DEFAULT_RECONNECT
    @reconnect = true
  elsif Numeric === opts[:reconnect]
    @reconnect_timeout = opts[:reconnect]
    @reconnect = true
  else
    @reconnect = false
  end
  @timeout = opts[:timeout]
  @p = MessagePack::Packer.new
  @u = MessagePack::Unpacker.new
  @s = 0
end

#_insert(space_no, tuple, cb) ⇒ Object



168
169
170
171
172
# File 'lib/tarantool16/connection/common.rb', line 168

def _insert(space_no, tuple, cb)
  req = {IPROTO_SPACE_ID => space_no,
         IPROTO_TUPLE => tuple}
  send_request(REQUEST_TYPE_INSERT, req, cb)
end

#_ipv6?Boolean

Returns:

  • (Boolean)


164
165
166
# File 'lib/tarantool16/connection/common.rb', line 164

def _ipv6?
  @host[1].count(':') > 1
end

#_ping(cb) ⇒ Object



230
231
232
# File 'lib/tarantool16/connection/common.rb', line 230

def _ping(cb)
  send_request(REQUEST_TYPE_PING, REQ_EMPTY, cb)
end

#_replace(space_no, tuple, cb) ⇒ Object



174
175
176
177
178
# File 'lib/tarantool16/connection/common.rb', line 174

def _replace(space_no, tuple, cb)
  req = {IPROTO_SPACE_ID => space_no,
         IPROTO_TUPLE => tuple}
  send_request(REQUEST_TYPE_REPLACE, req, cb)
end

#_select(space_no, index_no, key, offset, limit, iterator, cb) ⇒ Object



187
188
189
190
191
192
193
194
195
196
197
198
199
# File 'lib/tarantool16/connection/common.rb', line 187

def _select(space_no, index_no, key, offset, limit, iterator, cb)
  iterator ||= ::Tarantool16::ITERATOR_EQ
  unless Integer === iterator
    iterator = ::Tarantool16.iter(iterator)
  end
  req = {IPROTO_SPACE_ID => space_no,
         IPROTO_INDEX_ID => index_no,
         IPROTO_KEY => key || [],
         IPROTO_OFFSET => offset,
         IPROTO_LIMIT => limit,
         IPROTO_ITERATOR => iterator}
  send_request(REQUEST_TYPE_SELECT, req, cb)
end

#_tcp?Boolean

Returns:

  • (Boolean)


151
152
153
# File 'lib/tarantool16/connection/common.rb', line 151

def _tcp?
  @host[0] == 'tcp' || @host[0] == :tcp
end

#_unix?Boolean

Returns:

  • (Boolean)


147
148
149
# File 'lib/tarantool16/connection/common.rb', line 147

def _unix?
  @host[0] == 'unix' || @host[0] == :unix
end

#_unix_sock_pathObject



155
156
157
# File 'lib/tarantool16/connection/common.rb', line 155

def _unix_sock_path
  @host[1]
end

#_update(space_no, index_no, key, ops, cb) ⇒ Object



201
202
203
204
205
206
207
# File 'lib/tarantool16/connection/common.rb', line 201

def _update(space_no, index_no, key, ops, cb)
  req = {IPROTO_SPACE_ID => space_no,
         IPROTO_INDEX_ID => index_no,
         IPROTO_KEY => key,
         IPROTO_TUPLE => ops}
  send_request(REQUEST_TYPE_UPDATE, req, cb)
end

#_upsert(space_no, index_no, tuple_key, ops, cb) ⇒ Object



209
210
211
212
213
214
215
# File 'lib/tarantool16/connection/common.rb', line 209

def _upsert(space_no, index_no, tuple_key, ops, cb)
  req = {IPROTO_SPACE_ID => space_no,
         IPROTO_INDEX_ID => index_no,
         IPROTO_TUPLE => tuple_key,
         IPROTO_DEF_DUPLE => ops}
  send_request(REQUEST_TYPE_UPSERT, req, cb)
end

#format_authenticate(user, pass1, salt) ⇒ Object



83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/tarantool16/connection/common.rb', line 83

def format_authenticate(user, pass1, salt)
  pass2 = ::OpenSSL::Digest::SHA1.digest(pass1)
  scramble = ::OpenSSL::Digest::SHA1.new(salt).update(pass2).digest
  pints = pass1.unpack('L*')
  sints = scramble.unpack('L*')
  pints.size.times{|i| sints[i] ^= pints[i] }
  packed = sints.pack('L*')
  # tarantool waits packed as a string, so that force msgpack to pack as string
  packed.force_encoding('utf-8')
  format_request(REQUEST_TYPE_AUTHENTICATE, next_sync, {
    IPROTO_USER_NAME => user,
    IPROTO_TUPLE => [ 'chap-sha1', packed ]
  })
end

#format_request(code, sync, body) ⇒ Object



64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/tarantool16/connection/common.rb', line 64

def format_request(code, sync, body)
  @p.write(0x01020304).
    write_map_header(2).
    write(IPROTO_CODE).write(code).
    write(IPROTO_SYNC).write(sync).
    write(body)
  sz = @p.size - 5
  str = @p.to_s
  @p.clear
  # fix bigendian size
  str.setbyte(4, sz)
  str.setbyte(3, sz>>8)
  str.setbyte(2, sz>>16)
  str.setbyte(1, sz>>24)
  str
ensure
  @p.clear
end

#host_portObject



159
160
161
162
# File 'lib/tarantool16/connection/common.rb', line 159

def host_port
  @host[1] =~ /^(.*):([^:]+)$/
  [$1, $2.to_i]
end

#next_syncObject



60
61
62
# File 'lib/tarantool16/connection/common.rb', line 60

def next_sync
  @s = @s % 0x3fffffff + 1
end

#now_fObject



51
52
53
# File 'lib/tarantool16/connection/common.rb', line 51

def now_f
  ::Process.clock_gettime(CLOCK_KIND)
end

#parse_greeting(greeting) ⇒ Object



98
99
100
101
# File 'lib/tarantool16/connection/common.rb', line 98

def parse_greeting(greeting)
  @greeting = greeting[0, 64]
  @salt = greeting[64..-1].unpack('m')[0][0,20]
end

#parse_response(str) ⇒ Object



115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
# File 'lib/tarantool16/connection/common.rb', line 115

def parse_response(str)
  sync = nil
  @u.feed(str)
  n = @u.read_map_header
  while n > 0
    cd = @u.read
    vl = @u.read
    case cd
    when IPROTO_SYNC
      sync = vl
    when IPROTO_CODE
      code = vl
    end
    n -= 1
  end
  if sync == nil
    return Option.error(nil, UnexpectedResponse, "Mailformed response: no sync")
  elsif code == nil
    return Option.error(nil, UnexpectedResponse, "Mailformed response: no code for sync=#{sync}")
  end
  begin
    bmap = @u.read
    body = bmap[IPROTO_DATA] || bmap[IPROTO_ERROR]
  rescue EOFError
    body = nil
  end
  Option.ok(sync, code, body)
rescue ::MessagePack::UnpackError, ::MessagePack::TypeError => e
  @u.reset
  Option.error(sync, e, nil)
end

#parse_size(str) ⇒ Object



103
104
105
106
107
108
109
110
111
112
113
# File 'lib/tarantool16/connection/common.rb', line 103

def parse_size(str)
  @u.feed(str)
  n = @u.read
  unless Integer === n
    return UnexpectedResponse.new("wanted response size, got #{n.inspect}")
  end
  n
rescue ::MessagePack::UnpackError, ::MessagePack::TypeError => e
  @u.reset
  e
end