Tarantool development patches archive
 help / color / mirror / Atom feed
From: Roman Khabibov <roman.habibov@tarantool.org>
To: tarantool-patches@freelists.org
Cc: Kirill Yukhin <kyukhin@tarantool.org>,
	Alexander Turenko <alexander.turenko@tarantool.org>
Subject: [tarantool-patches] Re: [PATCH] net.box: ignore absence of _vcollation
Date: Fri, 19 Jul 2019 15:16:58 +0300	[thread overview]
Message-ID: <6D947FF2-9C44-40A9-9707-AA94512B27D6@tarantool.org> (raw)
In-Reply-To: <20190712095549.ac4hhaxhxzgaik5i@tarantool.org>


> On Jul 12, 2019, at 12:55, Kirill Yukhin <kyukhin@tarantool.org> wrote:
> 
> Hello,
> 
> On 08 Jul 15:13, Roman Khabibov wrote:
>> Ignore error about absence of _vcollation, when a client connects
>> to a server of old Tarantool versions, where this space does not
>> exist.
>> 
>> Closes #4307
>> ---
>> Branch: https://github.com/tarantool/tarantool/tree/romanhabibov/gh-4307-vcoll
>> Issue: https://github.com/tarantool/tarantool/issues/4307

>> 
>> src/box/lua/net_box.lua | 33 +++++++++++++++++++++++++--------
>> 1 file changed, 25 insertions(+), 8 deletions(-)
>> 
>> diff --git a/src/box/lua/net_box.lua b/src/box/lua/net_box.lua
>> index 2892bb3d3..723e63045 100644
>> --- a/src/box/lua/net_box.lua
>> +++ b/src/box/lua/net_box.lua
>> @@ -761,6 +761,11 @@ local function create_transport(host, port, user, password, callback,
>>                 if status ~= 0 then
>>                     local body
>>                     body, body_end = decode(body_rpos)
>> +                    local err_msg = 'Space \'277\' does not exist'
> 
> Space 277? Seriously? This code handles not only collations request.
> Should be more generic, IMHO.
@@ -685,7 +685,7 @@ local function create_transport(host, port, user, password, callback,
             set_state('active')
             return console_sm(rid)
         elseif greeting.protocol == 'Binary' then
-            return iproto_auth_sm(greeting.salt)
+            return iproto_auth_sm(greeting.salt, greeting.version_id)
         else
             return error_sm(E_NO_CONNECTION,
                             'Unknown protocol: '..greeting.protocol)
@@ -710,11 +710,11 @@ local function create_transport(host, port, user, password, callback,
         end
     end
 
-    iproto_auth_sm = function(salt)
+    iproto_auth_sm = function(salt, version_id)
         set_state('auth')
         if not user or not password then
             set_state('fetch_schema')
-            return iproto_schema_sm()
+            return iproto_schema_sm(nil, version_id)
         end
         encode_auth(send_buf, new_request_id(), user, password, salt)
         local err, hdr, body_rpos, body_end = send_and_recv_iproto()
@@ -727,34 +727,52 @@ local function create_transport(host, port, user, password, callback,
             return error_sm(E_NO_CONNECTION, body[IPROTO_ERROR_KEY])
         end
         set_state('fetch_schema')
-        return iproto_schema_sm(hdr[IPROTO_SCHEMA_VERSION_KEY])
+        return iproto_schema_sm(hdr[IPROTO_SCHEMA_VERSION_KEY], version_id)
     end
 
-    iproto_schema_sm = function(schema_version)
+    iproto_schema_sm = function(schema_version, version_id)
         if not callback('will_fetch_schema') then
             set_state('active')
-            return iproto_sm(schema_version)
+            return iproto_sm(schema_version, version_id)
         end
+        local need_vcoll
+        -- 131584 is tarantool_version_id() for 2.2.0.
+        if version_id ~= nil and version_id >= 131584 then
+            need_vcoll = true
+        else
+            need_vcoll = false
+        end
+
         local select1_id = new_request_id()
         local select2_id = new_request_id()
-        local select3_id = new_request_id()
+        local select3_id = nil
         local response = {}
         -- fetch everything from space _vspace, 2 = ITER_ALL
         encode_select(send_buf, select1_id, VSPACE_ID, 0, 2, 0, 0xFFFFFFFF, nil)
         -- fetch everything from space _vindex, 2 = ITER_ALL
         encode_select(send_buf, select2_id, VINDEX_ID, 0, 2, 0, 0xFFFFFFFF, nil)
-        -- fetch everything from space _vcollation, 2 = ITER_ALL
-        encode_select(send_buf, select3_id, VCOLLATION_ID, 0, 2, 0, 0xFFFFFFFF,
-                      nil)
+        if need_vcoll == true then
+            select3_id = new_request_id()
+            -- fetch everything from space _vcollation, 2 = ITER_ALL
+            encode_select(send_buf, select3_id, VCOLLATION_ID, 0, 2, 0, 0xFFFFFFFF,
+                          nil)
+        end
 
         schema_version = nil -- any schema_version will do provided that
                              -- it is consistent across responses
+
+        local function vcoll_response(need_vcoll)
+            if need_vcoll == true then
+                return response[select3_id]
+            end
+            return true
+        end
         repeat
             local err, hdr, body_rpos, body_end = send_and_recv_iproto()
             if err then return error_sm(err, hdr) end
             dispatch_response_iproto(hdr, body_rpos, body_end)
             local id = hdr[IPROTO_SYNC_KEY]
-            if id == select1_id or id == select2_id or id == select3_id then
+            if id == select1_id or id == select2_id or id == select3_id and need_vcoll then
                 -- response to a schema query we've submitted
                 local status = hdr[IPROTO_STATUS_KEY]
                 local response_schema_version = hdr[IPROTO_SCHEMA_VERSION_KEY]
@@ -767,21 +785,21 @@ local function create_transport(host, port, user, password, callback,
                     schema_version = response_schema_version
                 elseif schema_version ~= response_schema_version then
                     -- schema changed while fetching schema; restart loader
-                    return iproto_schema_sm()
+                    return iproto_schema_sm(nil, version_id)
                 end
                 local body
                 body, body_end = decode(body_rpos)
                 response[id] = body[IPROTO_DATA_KEY]
             end
         until response[select1_id] and response[select2_id] and
-              response[select3_id]
+              vcoll_response(need_vcoll)
         callback('did_fetch_schema', schema_version, response[select1_id],
-                 response[select2_id],response[select3_id])
+                 response[select2_id], need_vcoll and response[select3_id] or nil)
         set_state('active')
-        return iproto_sm(schema_version)
+        return iproto_sm(schema_version, version_id)
     end
 
-    iproto_sm = function(schema_version)
+    iproto_sm = function(schema_version, version_id)
         local err, hdr, body_rpos, body_end = send_and_recv_iproto()
         if err then return error_sm(err, hdr) end
         dispatch_response_iproto(hdr, body_rpos, body_end)
@@ -794,9 +812,9 @@ local function create_transport(host, port, user, password, callback,
             local body
             body, body_end = decode(body_rpos)
             set_state('fetch_schema')
-            return iproto_schema_sm(schema_version)
+            return iproto_schema_sm(schema_version, version_id)
         end
-        return iproto_sm(schema_version)
+        return iproto_sm(schema_version, version_id)
     end
 
     error_sm = function(err, msg)

>> @@ -1270,16 +1275,28 @@ function remote_methods:_install_schema(schema_version, spaces, indices,
>>                 local pktype = index[PARTS][k][2] or index[PARTS][k].type
>>                 local pkfield = index[PARTS][k][1] or index[PARTS][k].field
>>                 local pkcollation = nil
>> -                if pkcollationid ~= nil then
>> +                if pkcollationid ~= nil and collations ~= nil then
>>                     pkcollation = collations[pkcollationid + 1][2]
>>                 end
>> 
>> -                local pk = {
>> -                    type = pktype,
>> -                    fieldno = pkfield + 1,
>> -                    collation = pkcollation,
>> -                    is_nullable = pknullable
>> -                }
>> +                local pk
>> +                if collations ~= nil then
>> +                    pk = {
>> +                        type = pktype,
>> +                        fieldno = pkfield + 1,
>> +                        collation = pkcollation,
>> +                        is_nullable = pknullable
>> +                    }
>> +                else
>> +                    pk = {
>> +                        type = pktype,
>> +                        fieldno = pkfield + 1,
>> +                        collation_id = pkcollationid,
>> +                        is_nullable = pknullable
>> +                    }
>> +                end
> 
> IMHO, it'd be better to not duplicate code and put actual difference
> under if-then-else hammock.
@@ -1270,16 +1288,21 @@ function remote_methods:_install_schema(schema_version, spaces, indices,
                 local pktype = index[PARTS][k][2] or index[PARTS][k].type
                 local pkfield = index[PARTS][k][1] or index[PARTS][k].field
                 local pkcollation = nil
-                if pkcollationid ~= nil then
+                if pkcollationid ~= nil and collations ~= nil then
                     pkcollation = collations[pkcollationid + 1][2]
                 end
 
                 local pk = {
                     type = pktype,
                     fieldno = pkfield + 1,
-                    collation = pkcollation,
                     is_nullable = pknullable
                 }
+                if collations ~= nil then
+                    pk.collation = pkcollation
+                else
+                    pk.collation_id = pkcollationid
+                end
+

commit abc88ef8d38e21a6c7faf925a19105ce65d45467
Author: Roman Khabibov <roman.habibov@tarantool.org>
Date:   Mon Jul 8 14:52:48 2019 +0300

    net.box: take into account _vcollation presence
    
    The error occured, when a client connects to a server of old
    Tarantool versions, where _vcollation space does not exist. After
    this patch, _vcollation is fetched depending on a server version.
    
    Closes #4307

diff --git a/src/box/lua/net_box.lua b/src/box/lua/net_box.lua
index 2892bb3d3..9fe792195 100644
--- a/src/box/lua/net_box.lua
+++ b/src/box/lua/net_box.lua
@@ -685,7 +685,7 @@ local function create_transport(host, port, user, password, callback,
             set_state('active')
             return console_sm(rid)
         elseif greeting.protocol == 'Binary' then
-            return iproto_auth_sm(greeting.salt)
+            return iproto_auth_sm(greeting.salt, greeting.version_id)
         else
             return error_sm(E_NO_CONNECTION,
                             'Unknown protocol: '..greeting.protocol)
@@ -710,11 +710,11 @@ local function create_transport(host, port, user, password, callback,
         end
     end
 
-    iproto_auth_sm = function(salt)
+    iproto_auth_sm = function(salt, version_id)
         set_state('auth')
         if not user or not password then
             set_state('fetch_schema')
-            return iproto_schema_sm()
+            return iproto_schema_sm(nil, version_id)
         end
         encode_auth(send_buf, new_request_id(), user, password, salt)
         local err, hdr, body_rpos, body_end = send_and_recv_iproto()
@@ -727,34 +727,52 @@ local function create_transport(host, port, user, password, callback,
             return error_sm(E_NO_CONNECTION, body[IPROTO_ERROR_KEY])
         end
         set_state('fetch_schema')
-        return iproto_schema_sm(hdr[IPROTO_SCHEMA_VERSION_KEY])
+        return iproto_schema_sm(hdr[IPROTO_SCHEMA_VERSION_KEY], version_id)
     end
 
-    iproto_schema_sm = function(schema_version)
+    iproto_schema_sm = function(schema_version, version_id)
         if not callback('will_fetch_schema') then
             set_state('active')
-            return iproto_sm(schema_version)
+            return iproto_sm(schema_version, version_id)
         end
+        local need_vcoll
+        -- 131584 is tarantool_version_id() for 2.2.0.
+        if version_id ~= nil and version_id >= 131584 then
+            need_vcoll = true
+        else
+            need_vcoll = false
+        end
+
         local select1_id = new_request_id()
         local select2_id = new_request_id()
-        local select3_id = new_request_id()
+        local select3_id = nil
         local response = {}
         -- fetch everything from space _vspace, 2 = ITER_ALL
         encode_select(send_buf, select1_id, VSPACE_ID, 0, 2, 0, 0xFFFFFFFF, nil)
         -- fetch everything from space _vindex, 2 = ITER_ALL
         encode_select(send_buf, select2_id, VINDEX_ID, 0, 2, 0, 0xFFFFFFFF, nil)
-        -- fetch everything from space _vcollation, 2 = ITER_ALL
-        encode_select(send_buf, select3_id, VCOLLATION_ID, 0, 2, 0, 0xFFFFFFFF,
-                      nil)
+        if need_vcoll == true then
+            select3_id = new_request_id()
+            -- fetch everything from space _vcollation, 2 = ITER_ALL
+            encode_select(send_buf, select3_id, VCOLLATION_ID, 0, 2, 0, 0xFFFFFFFF,
+                          nil)
+        end
 
         schema_version = nil -- any schema_version will do provided that
                              -- it is consistent across responses
+
+        local function vcoll_response(need_vcoll)
+            if need_vcoll == true then
+                return response[select3_id]
+            end
+            return true
+        end
         repeat
             local err, hdr, body_rpos, body_end = send_and_recv_iproto()
             if err then return error_sm(err, hdr) end
             dispatch_response_iproto(hdr, body_rpos, body_end)
             local id = hdr[IPROTO_SYNC_KEY]
-            if id == select1_id or id == select2_id or id == select3_id then
+            if id == select1_id or id == select2_id or id == select3_id and need_vcoll then
                 -- response to a schema query we've submitted
                 local status = hdr[IPROTO_STATUS_KEY]
                 local response_schema_version = hdr[IPROTO_SCHEMA_VERSION_KEY]
@@ -767,21 +785,21 @@ local function create_transport(host, port, user, password, callback,
                     schema_version = response_schema_version
                 elseif schema_version ~= response_schema_version then
                     -- schema changed while fetching schema; restart loader
-                    return iproto_schema_sm()
+                    return iproto_schema_sm(nil, version_id)
                 end
                 local body
                 body, body_end = decode(body_rpos)
                 response[id] = body[IPROTO_DATA_KEY]
             end
         until response[select1_id] and response[select2_id] and
-              response[select3_id]
+              vcoll_response(need_vcoll)
         callback('did_fetch_schema', schema_version, response[select1_id],
-                 response[select2_id],response[select3_id])
+                 response[select2_id], need_vcoll and response[select3_id] or nil)
         set_state('active')
-        return iproto_sm(schema_version)
+        return iproto_sm(schema_version, version_id)
     end
 
-    iproto_sm = function(schema_version)
+    iproto_sm = function(schema_version, version_id)
         local err, hdr, body_rpos, body_end = send_and_recv_iproto()
         if err then return error_sm(err, hdr) end
         dispatch_response_iproto(hdr, body_rpos, body_end)
@@ -794,9 +812,9 @@ local function create_transport(host, port, user, password, callback,
             local body
             body, body_end = decode(body_rpos)
             set_state('fetch_schema')
-            return iproto_schema_sm(schema_version)
+            return iproto_schema_sm(schema_version, version_id)
         end
-        return iproto_sm(schema_version)
+        return iproto_sm(schema_version, version_id)
     end
 
     error_sm = function(err, msg)
@@ -1270,16 +1288,21 @@ function remote_methods:_install_schema(schema_version, spaces, indices,
                 local pktype = index[PARTS][k][2] or index[PARTS][k].type
                 local pkfield = index[PARTS][k][1] or index[PARTS][k].field
                 local pkcollation = nil
-                if pkcollationid ~= nil then
+                if pkcollationid ~= nil and collations ~= nil then
                     pkcollation = collations[pkcollationid + 1][2]
                 end
 
                 local pk = {
                     type = pktype,
                     fieldno = pkfield + 1,
-                    collation = pkcollation,
                     is_nullable = pknullable
                 }
+                if collations ~= nil then
+                    pk.collation = pkcollation
+                else
+                    pk.collation_id = pkcollationid
+                end
+
                 idx.parts[k] = pk
             end
             idx.unique = not not index[OPTS].unique

  reply	other threads:[~2019-07-19 12:17 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-07-08 12:13 [tarantool-patches] " Roman Khabibov
2019-07-12  9:55 ` [tarantool-patches] " Kirill Yukhin
2019-07-19 12:16   ` Roman Khabibov [this message]
2019-07-20 19:07   ` Alexander Turenko
2019-07-24 21:27     ` Alexander Turenko
2019-07-24 22:43       ` Vladislav Shpilevoy
2019-07-30 10:58         ` Alexander Turenko
2019-07-30 12:08           ` Konstantin Osipov
2019-07-30 20:18           ` Vladislav Shpilevoy
2019-07-30 22:35             ` Alexander Turenko

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=6D947FF2-9C44-40A9-9707-AA94512B27D6@tarantool.org \
    --to=roman.habibov@tarantool.org \
    --cc=alexander.turenko@tarantool.org \
    --cc=kyukhin@tarantool.org \
    --cc=tarantool-patches@freelists.org \
    --subject='[tarantool-patches] Re: [PATCH] net.box: ignore absence of _vcollation' \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox