[Tarantool-patches] [PATCH 2/3] box: introduce _session_settings system space

imeevma at tarantool.org imeevma at tarantool.org
Thu Dec 19 11:32:58 MSK 2019


This patch creates _session_settings system space. This space is
used to view and change session settings. There are no settings at
the moment, some will be added in the next patch.

Part of #4511
---
 src/box/CMakeLists.txt                             |   1 +
 src/box/bootstrap.snap                             | Bin 5921 -> 5975 bytes
 src/box/lua/space.cc                               |   2 +
 src/box/lua/upgrade.lua                            |  15 +
 src/box/schema_def.h                               |   8 +
 src/box/session_settings.c                         | 409 +++++++++++++++++++++
 src/box/session_settings.h                         |  61 +++
 src/box/virtual_engine.c                           |  52 ++-
 test/app-tap/tarantoolctl.test.lua                 |   4 +-
 test/box-py/bootstrap.result                       |   3 +
 test/box/access_sysview.result                     |   6 +-
 test/box/alter.result                              |   5 +-
 ...h-4511-access-settings-from-any-frontend.result | 108 +++++-
 ...4511-access-settings-from-any-frontend.test.lua |  37 ++
 test/wal_off/alter.result                          |   2 +-
 15 files changed, 697 insertions(+), 16 deletions(-)
 create mode 100644 src/box/session_settings.c
 create mode 100644 src/box/session_settings.h

diff --git a/src/box/CMakeLists.txt b/src/box/CMakeLists.txt
index c011bfc..2cb81e8 100644
--- a/src/box/CMakeLists.txt
+++ b/src/box/CMakeLists.txt
@@ -79,6 +79,7 @@ add_library(box STATIC
     sysview.c
     blackhole.c
     virtual_engine.c
+    session_settings.c
     vinyl.c
     vy_stmt.c
     vy_mem.c
diff --git a/src/box/bootstrap.snap b/src/box/bootstrap.snap
index 7ff3aa5984dbe41a6d4fef7a9ff427336691784f..c573eecd01cf7c7ada949571750f5ba7f30a0e58 100644
GIT binary patch
literal 5975
zcmV-d7pUk{PC-x#FfK7O3RY!ub7^mGIv_GGGcGVKGB+_TXEtUxFgamj3Q2BrbYX5|
zWjY`-FgP?}HfCfkVliSjEi^JPHZ5XiVPh>}W-~ZuIW#jeW;109RzqxWV{1AfdwmKD
z)w&D1%@*GP&H{cG{G|W at 0000ewJ-euP_?!I`p{@ENf2nO>HuFnz!wkj#k+nW%pPgt
zBZ0)WtpN`tMI1&W;^gZsQ&N;l)}E- at Bxx#$t*xi7PvyfprWdR<qHD&edh~*lhI(p?
zO)caC=K`_<Z~kv%<)pw3o8_FK4QC~wfU^-yz*){hAi)C>(4G!J07hhyME2Rh12qO5
z03$jVXaJ1pRDgk60$>Z!*eC$j5|Pg}34qnqumK~c0b2t`L_iG~k?1 at i4HzdHfB+|Q
zBANqOVgUxQ#40o_ktH4rAQGvnh(zbqk(fnv8maP`cPgLx#(XB9 at vq<g`z_`D_S@~l
z-AWBNcZYkpi|uh``Eex{kLz(g!@lb#zUzACUEg)M*HyT#s~)baQx&djs at FBBuFjll
zO+Zj<G;2Ko0kx+9DD4@*08 at EIPUZCpfB@@iCV+J<1HigE$(VVEW6HckF=XE1I|PoY
z)%l5`)$sw9wj0`ob$UOcFpN(qjOq!UyfEx at 7e#wQ at z^ayK6Sg=7Z|85{G!`JI{PaJ
zW(%LbY at wIj7H*-l%ac%u^CA>FbrA}kH{AbCPXF6(|2w%f)%I+$Y2l*g{=M$Xyxo7R
zxqlS(dQX-uShQ$;C5zTpu(X=#N~@Qww7S(*n6##{r1g|4T05ms3HoPkO3*)PQi5JZ
z2K`g1R@;+AqwR^J^s_1bY<r+2)xMrYp?x`lLTpp?MR883R=tRA8`QjAT@=+{O`c?x
ziIc1%HOXpLkC+^nARUiNj*iD9OFR-K-XBTgy%8iib<U3D)M;cSr&&357Maz&ii~Jp
zM2axke!O`NDe^*ycpqel_e4VYP!P_65OMxvNC$lY(LtdfI;ev^d{kBO5UQ%$(W9y=
zh==z&c6gs7$a@?*dcTpQcN;i*uW_STq+z32oKd4#%uX3JYB6T0yiK*&qQQ_M%vnkv
z6=u}=BF3?2zJp637{%RP=1$Qq*$W_9jLos<{k#6n^$)r3-#69F0p4;*tkpK%{AFUS
znGg_=EXF3yoH9MzF4wfgnzuX|!<q>J$zp6Ukc_w6cWq?C!9cPYn?E>A-6&NqF0E!k
zI2Q90w8jVx3r9_$vBB2D3t4PUOe4yLeFSlH5$V6%CUe at dOZWJ@=2NXQ3yZh=XO?YK
zbPEd+_0eoFv+T=Jzq$0wW~1`RGm_0w6Olu{`}fN=R%v2Xzo?7KT-0moQ6>(;VY&CL
z)U5k{CHE{+)qJ=;f1BDp{-nB5oo3fJbushgnm1V8sQb2k*i;kKY`YTE%m%ge*Q{1i
zRrjuiT1D9--$oP<#yBj_YzT<Zj~+hWwTg$(jvhfgG_md9>)27dlOu?B2ZxS*<lDV-
zBS-Da1`gU+jT=vzQjHcIe$lW|!!x4>O$H9bVQUqgyiOVJAc`l(jI|1ejJ4`TjJ0a5
z0)kPK;V>LV!#E7+c#PpN99H`ShBXtyVN+AiE at C)r%E`r_+H;F8XiqJ;$WzEX^~_?6
z)`*1`t?`O1T4QUp0*h^|;)-pg!isI&#wn`kuM|}DH;O6x+g~W8c;6?YcwZ-=c%4l=
zQS)NL37XduO at O^w!`Dj*Ci+ieiT;sLqW}JnNaBAZkododBmQ?1VZ{GK6!E`P2qLna
zK at 72eAcR=|4?(Pd{XPKke-A(W&w~&DJ9p?Ie;s(pKZhOi&mRXJYI$zRftJSx9E`q>
zs*Al9>W-pDpQnZ!yr;ni?`NpNJ7u7u<`u&XG%pxrVE(K_yZ3q_hVET}p?g0sbl-iL
z3sN4;kCbmAOv+1n7Qnn;p#|?%V8QzoR`4DL6}&$o1 at ANgg_@o|C(!ipF(KWm at 9ODR
zQFMDfCG^>z1U}o3P{Q`xi$H?*A&j6s2qI{&{RbgrzXycu^?Z<h_FsG2o<~pH at qD$t
z?RWC9t_OHnw}U&Z%er13WY<my*{$Q1-R#n_)7xjA-a6^@wzpl+V$0<$wp(4rw%BTM
zHMd&NnOb0;BmHyP<Vq&z$tCAVWsqkjgPa3okO%pktiJ&V|7$Sk{|q+h7--P at 1sU{i
z0S2s`3s|-S3s^Re9AXixf~z>hBC!Yu%V>OaWwe50G`a~r+tV$HW1PV`@ou>tkcnaJ
z-!9jSTH+UL7alIE%x{T-hHZAapDqV%LUmz$To@|X`z5hV$V9VJQ?kOOWK>gnLQ{Ie
zq?APKU``qvP=|EWhYugk+cx|aHs{!YIwWp|d_(Elzfho1wLuRs?h)HzcBIj$G9eQG
z^at6DRRXM3w224!3GgKV`~<+08O)^&7cxv^n8Yvvt(LN-Uu?+-Wc6mLrxZphN{N at W
zOM*($A%Q{q;sz;q^mOFK%~6*b&T8glbh9#QDzX)EDcZ97yb{qeB+C#iL#_~6Az~t0
zlF5duU at JF#@DP=uDL$n5s9{VKQi at r*>7!q%&EKUOt@}^Lf^Znt%qWRxWS?Wty>*NF
zYpId3`TczxnSRLk|JtLx-QH`D+QDd|Fq?0<@Q1<%GuNo!TWXsozei%F=o7O~xY#z`
z%BuVFRxACvsN~|hXID#Q_nON2eCPf>Z&Q>gM4wo7lHH`TYp#c=-(6f+bnvf<(n|lF
z^0$9f3x8qqW;opaqfPvT^d_yof7ujmVlGF<-Cd?7L(OjE?ygqPY)-e<PxYB#%cXVu
zdG14|ad#J0;w2?lUHjLFF0oRQ^}qS5YyYB3oP-2U%3q-oU1FpoU4J&C-)FY#XWdh#
zE*9IA*}7Dk$+9^`S at z|srfP#K&mQ%=E8X93zKdOdt)hO{@j6X2%1U`UKM!>u4zrf$
z{r$Q#{btc(?%CZ!HQ)bjd)HBIgUMljhdi^*_iNuHwnNHaA*#ejMzD-16VGNnyULBk
zqS7kg=n at +l$uXi^xTwg_D*D7kig?y++XmV6sMj>7%HQ+%N~+9v5!v-nf4-Tn{yr&(
z>sLy9R0|Iw632)#G0~8pi at g;thnW>BKY!a4Raw1-Tzn6?UdBO}cu2^U-bR1)0Y$pN
zTyO!}LiR-qrYw}OK)PaPMNt(*RA3)d$b at j1Qi@v?O;FgL;NrxVCbTe-WeF at wTuH(T
z5==)d8BwJODnv{fLW&TzAZS1+{gC8Clpdh)@MH%kIyA|F2 at Xg%9NDm>1|>8knE{Cm
zM`ADn!|Vkk7mD~P3L^qGqy-@?1X+Pdg`pIHpzz}aA0`O(>A{Cb2|Gv#8bOB$IYPhz
z!i^7X?5UxL#@CEIGVsK>1H*$C9RPXB>|hzbnl0h5KY#xC!E}aV+IMZ-{B1s8$YS_v
zw&d*EeZ3MF=}I^2>du9MxHQ}LWV+el>n^eEYL<k<_%5nhiSgAeNh`}xxVlHr+Q4*4
zn}ji=r;fXy<bs*f#?=UdQeOQNH?OIdny&qu{9eC9C5~OqlA1Q0PKj?!UlTVibzyu+
zD>o|FMo33UYHr!1-?jJI$OuWRZF(dH2b=P5zPTh<|GH1S1^M+5{rP*8mGY<)YsuOH
zn>Y&xON?a>?<uFlfywE%@Rbdmc0itwiLGeh^Wk($%#^{;hU<A@;w21tz9g=4!OhnD
zk-;%B6$^g892wjaPm$BZiNPtclnQ(}osD;E;#wRV6cW?0a!^RDbj9o8%rtQloSaSv
z+%0jGH%&ZU(-wweCB}xtPu$pkyq^*~X#?~jaT5x9VSGu<WP&IqMv_36g^wa2gG1sa
z5cryGNUY=mFgaZkCviZDku<Oa@^0uDUQY`jVc>`R-FRKt$O1elB%Ue2<LSC6u~7oH
zryCb8!UpZ(em7gs_H?U*i`IDA<#ajRjfsh<$>DBEJR}Vi&uM4tEwK;;bUNU!OKypS
z959BbQ(__ma8Xe}B_2ZKv;*>bN(`icU(UyiYT_SNPd_g^oNkGI9EGT&plm;%9o%CI
z{q1nQ9`M$Mc^JF&e!eE&@#20qrzQ^iP`O_c>+m+GB+k*x*qnB at oDTR!3*(Ub*={@D
z4UGcwdS1Hl4fp430{WKNMtigAqHsMXuEBpiU>GH)QQYxzz8+2t6VG7D;GU3J1~G at Y
zsDpzmno@{n0000$001)^1Q3MPtdp<`699mLf`h{3QfMR;2x1s0lU0-<1Aw6b0+2ue
zNN50D9hCubUzk=eTWMHeEeQ&&B|(90jA<`P9Ct&ez~Rer*3`U!r6X+ry+u20F;1$I
z70`5q%&)abhb_iQRk8w_j*$7a7U{6XIH^ijK+_R2zt$ohwiqW>$qHyXLgv?6q{9~D
zq$*hfO-IQ5T8nhpVw_YZE1>BJnO|#>4qJ?WR6Jci8k8niGsf3Nrrw5(3?4)kg3YMe
zXbNE}MyPcxl_H}!5o7*%K2cd=DZXFVK|h8w7!m{K#c}>?;JLZS<Klsk+KSw=oTlUV
z+&@~K?kE90x2e-iAri04kM at 1as-x|jjuJnE&D+2)3cZ0xkZ1#TB-P!;`M&lkkwWO@
zRKScMR2Gp;Nt`^`w$S89<bWx0awIev!{CadYNB>gRG7BO!9wB4@@L>g$VDhe2ucz5
zU~NTvkE#RWIw2^b=UX~OAHtj+AzxBCNI752$H at ciA{0tkx)$?Z)`EzLv0KnE^rh5E
z!S&j4Qehm$J5tgPI?U!0yZc}qip7vNMR?ua0)8Mex6 at 1@n!>M*>k{K!bh|^BqQ~=E
zQSM>5D<X-c(sjQaI&5staeJz!R$jS*rNVe~aB~8xaKrYSDBcTSuD at C3V;N)Dm1v^7
z)ca{l;n!~O0;89}4vjrUDMIn?1$_NDC%!yI+E4Ge{H~9j7>OkG at t(`mbHBvb{S6Fm
zGt)UTp4D9AH_<*CLwUsdxSxAo<c&zT?CBRW)k%Wv_RW?pFc4THd2P&=+QwO{A^y-a
zL`uZJ>+mMPHArQ!-_+ at 1hN@InfbB6I`=t<7)YGHq<by6fKJlTnzbI-vry=#npA{lz
z2&#u{@OwKD-+g at K%L}C54P9(-oYB at G;}=2b at npk`pw>8(p+yi&hCJk+j9Wrb-r5g-
zBI(pP-Y`UQ7<~o&C;BBp=$YQb=mS|oP_^2Rz`z+rH&4bb5)(n`@g~Cy34*7`lg$Rm
zBXcuMdJ7C0bC}d{If&GR&G)!C&cI`y`B(1MdL<Z5H};=Z&M)5piZUTog+ax^r}`Wz
zZr>vVetgQ8ff1`^Jr$#=;ClYWHM5vW-`4ZOUxT^~9eO5EDqDWVDz0MiU&UhCHMx&w
zPIcwu6A+n|dD5|~wtkbm&#X6-&Jj2yi-Ikjg3|Vz0k at uO12CVz_R1A_BU(!Y989Y_
zCw+23J8Q0bRE^$P09@>CjuwnMsoA_U$qT9vt`Wqh%oL7OhqB(_p+&~hmz4a?lsyDD
z at 1hT0L4HPXODI)m2z^bLHeZc7YZw#Hu*MKQKjx`v><(#5I{RK?XDE<Gd*k at uZaZP?
zx{R`t5EK4QX0lmL8c}W{gJ at dzSz=kyj0;#M{vpLZ!tW>G_Sj+S(pGg*h;D<e&=dn<
zoAuvTI=)UJCnhAEJ9yVP at h5U47{~eG4F&&aiiJu#OgGcKO`F at wUztwyp<Cz3QGB^A
zY_%Zt;jkQUb%=4S2I+X}FC6YR(Ixj?dv*@nNxy;gX5m6xh@;NME1}UROo<$J=&v%X
z;4;!>wp0Y=tCjQe632739JB^jPAc(pnd6wFVgiims0HUm!gQ!nt1K$GHVIM0bS&l^
z8-u0$c8Vo3=ZKF;J9q28e- at oEcfvD%KIlim$qBr}rGyBig;ItnSjLLlxCsw?N;;uj
z2?YHwV!<3cRVhHMbBXe*J(<F*LBK6Po at qu-(F891kKcS6MRRl!N^0p+tMe?bRiPyS
z8}`MXq#jMy+!2Bo7kJW+L34UOG=7qVH}k!&2jSHwa;~Q9O^w3*$Z3rcn8UqG at dhbw
zx44wC{?pQo87{QHkZACS43EUEnX#|+2jNZ<gEBN?z+eXJo~{d+i{B|@q+~!K<pU4P
z2v~HIOE-NfyL_fE&E3?k4yu%qQWzF=5270!;PQN4)fiNhvi!{{`hRqx+d<?v at bpI{
zK*)!pf6=*VXtFP2J3*3C6ryy%4Jo70q~g8`B~M9Wp*@X2iG=l@=<$N83m~^92O)Zm
z7S0T_j-C;e7T1tkP7n at 8N0O*x=*KO{A3N6`4bh?19#8>U{I_oCO&fIiIU#R1>xSmQ
zG~0-3Nr?;y<1&LGbdlIF`{ck4 at l)s2!(eK#H6ScN6aTIm{cYEpEQClbHhk0;SJP)t
zYLul#z at uBlgPpez!>h<*NvMzx_S-k~y?G09fMFLAEp8dc=qs{V68h43G~R=kG at 8|z
ze&-$2Z6ELTF>$u)oV;isdO|I^K?nb>8~M5&AC%c}dxx*|nC-r?tV?Klhfu>>qv#L+
zL&Q>hHZVlAV6CKKk<kaj!lnw+j|tMrXj3kD3H>Cq*ucNfWu~pSs2F;6*5pF-iM1o5
zwBBu&x#j&==*!*PK07+v?kBODnSbp9Ttqq3U?#+LAXE$X${Dr}UO1E%Rgh*3uuhGh
zQlVeyhb at Q)8t+~W*P+!OP(cu6DWT6&1Apu&hte_%(ue_OQ^Qjt^bhUe1 at S=R-K*g`
zwAuqI2!bpn^jT`)j~(SuT1G({F~DqUcuIu+p&b?^wo~9C|AFiSmM#F+VXA$>CZw>^
z1<HcTz<zXm(KrylV~Z2RB7$!KrL_)HHdIFL<MWDKcF6uE=3gF9+`UEqCnEpR`9*dj
ze2JFXZAQLN6zMuwq4Y{Ocl~KT(d=p4pO7%{dy;92{{#t?P2zJPR1bE`8M_8vJV+Le
z%rq%>UOY5C9%(`XqY?Mc!pTUvAjP<_-Fl90Lx?<%_%O1SsqMxM1BJI$=y)ENqMeL5
zXvFYZ$x0;Q?mPOiGDiae at _`CM<46KoMW0w7&Hs$#kdBudfmRg^gA#TX`F=m94KVVT
z7i}Sa=rbX^!K7jM6;rJwd^tsEoP3u=`zb-mg~=I34z3jvg<)%=T3~J%e2J9Ph+57L
z*NZ3u8T981UI-7gtby9lX&7EbR8tZ~4vzkdC<YA7VWry=AKOg$YA})c`fZv_-xa^e
zu%@*7DkbFo+Hdn1`QD%x1_BG+O1UoN2(aAA>v*GyjL9(#bkGVa117kEYZ$a~zqvUR
zX~CJXkJE_~kvq0hB$^<h`vXkIQ?3)PsFZ>wGK0FH&EVi++YNFp8x8`?utQ_<GRM!c
zEDpL&gcX!yaE)oUZ&`%htF$2oM+a2|)be|H!2R-eiNhmmI{;o`r7YIOp_0LuoY)(Y
zbwrV(#}Wr#QeJ(XQ~%ljAcqK<&LkJsfI1dG=3x2yuPsc#dO_oPx#dea98RcD<|kGA
zTUkkKncfnZpT~ZSr|<fl?8e+8jTJ&4r=#abs?CD>RZjnpiXSn9r)&sA_Xg|WY6BRD
zo}bhOpB@;BLevumqE&Tcm(BJ)F0fA6t&bK*bxKLBtV35r4(Ws)EM0#K*8k<S!9frk
z4BP~W&fjE;l7wqShOI0hc*m7EKcYdfXZ0-gFc7f5e4s4{@JIk42fgI72F-U4v|vv^
zLI6CLhWO#^Dy&%CO31loB$OnWO!H25)=Y=?7{s>5CeJ{w_ietMSep)Hp#T83n;%r;
z20jQv%=@1hy_g)9h}q+nqS7JU3Chl1dCr@>M^a{TOLN at hJ(4n$Tbko0?~#<5+)~e^
z>5R)SIole7{wtP|Eg}7NKgX)nif!^Y`y)Da=L=$iK1CAMD>;voojrs}%5Q1-p%2v%
Ft?dNQUb6rI

literal 5921
zcmcJR<x>=n*Tom91(r^wTT+$<mWBoC4v~%pmi*E!(%oH)(%r3;NP~oQw+PZLx%_<o
zi096kx$}8-Uz|B-u8ulP6PJ${48hg2c5}CLb`oXa=Y{a{@$f^SJT?|^OFm&s3n&;@
z$;sWr!pYKFlz~r3$O0;8$<Kp;3kdNDzy+;&;6e})9)7sB2t)({hd>}!xO%dV&Xx|M
z3?Dw?;?A|>wU1Mj0Ve*eqVtph{%>Blym<m>UN-|?O)T;%5xE$8@{RHJfgocHMn!R9
zZ+eEAlJ|W3038zm5MR)D1}+`#H0Al)@+B5K8R*T8%Oo0WrKzQZviHaHvRfu2yQ7I5
zu0MjLI7=@!UevrG`?7U}LGGgW0$2FQ5|AxOIwbot7}y<g<T at -$8x%C(gKpNxhECv*
zkHiy@*4c~=Hb7!_FK<na$Ope!&Ji+`6*P0~j=-tDdqsc*mfvmnp_6RNN(unby!3m}
zj*><JUc&_On4m}<-98JQQQ`hqLa{m`<6P-8k8t(WncIa^)KkJmz{9cEmQzs}vZI%0
zwSWFg<LVcJ=)t)!r4}2Wgd3h}m$j#ytB0?Q7vAA5v{Ya%2+kei>MkJETi5{Qf;la8
zL4X_`fX8o;IiRAGuH at nXLpsP)j<l!!Gn%;x67jRMm*2*e at g=10j2t!k^Wb)P?BFV3
zBnSWayQsJspKvK9Naj3be2r?pA~Z)N&+CYQ?vn`ZxXRcJLBz;0!>8kL(xy;#3ojy&
z6SjB#-2ewwXD|*HvKu2*ZRI$ywDj4b^%-fJW$V{I`^87g{n^yrdi~_v+^STJUyY3l
zC696QM5CMox1nKITFIQUzTw&dmx`g0)^z(Qc at 0vx8qk%hhq?a=!YN%x7rdVRw&)Km
zXZ%W4>0&O$Ur<6j$<|b>bgVO9 at ntK=ePJ7$Zk0)2E2jN=EpLo{9lKWJ0fw?(;%6(t
zDtYxdwS+i%HhKA-6gE>F($iG#bGqo1Tp?>Ew`Fdb6rJi^p~PWZlecnByvzz2j?m at y
z7$RRL`A&N6{s%@TV_V>!OoT8YQ*p3#n60 at c5&mosy>xlGKZcgp^({;e^H<*oI*HB=
zv|n8WbX|LkQ(^?PT^qwNmgOE8%lsD@%WpP(>gJb%y6dIOHse-5frx6BL at da19Jp^0
zvLU^j2--e5aVsm=;~vxi%?~bKqD%sR--jFjJ<WFb{pk3GdEOrBgyKC<=ic9A$8sn_
zOuRHzi?q~+j~gX~nT&)4!0Ux>*#}pSJ9v3{dZfVmNXgp at Cl5~2^mqIWpwIz8KNf(k
zrBtFs7C(XtOobfW5X`hs)qmf)Ce`GKEHo6hjY>oWXIq;k+;^3j2~noXe@^@_&d-PJ
zV(r`e#tLn8<o#PURYakwP9iUuDB$<HyLQvbL+Wai!aMh^n at 4N=h1=u<dCwe^$=Uv~
zWXDZ&&!UqRFGhEK)uv-nRS4eLv{{p(+`F|70()}ncz?<%F{&LKn(U;cd<LnYPOkLC
zd^)Kh|9y*<Z+lar2pjC5V+jOwE5mIL>_Y at OlmxVpI%<*JCYEK;>#N4#P_MGV_?P&P
z{gdf2>ZVmdC{Y)rXi%9obWoYxa!|QN`)N3T;EYtthDs_hPM#`Yo4saoA)Om2RZ^T|
z(Q~F#i6c*+a~aErQ2$pC+C$vCN87Qj!{L<wxyJG?!;NM`Vok>2u_pa8u_mhnT#fs6
z<oZ`_F<kd6W}MYN8yuBBW*p@{NG(;^VTeqO!2+q4f0ur5+Yg-A_s-kVsBD+QXH=%`
zb|7oktyDBC%9*L4|5<_MJa7icQlBG7(-6QEr~gbOR~`5yLv$WUB>PAhM)V8~1TqEE
z2MvFVq`#QV!=|_O@!GeDP{5{(=}xGO?!rGvD3nWNkEHD!f?=OJ4}XXL*AqPdt`EP7
z_m!hQDp$7SG^Zfq#5%v=feNwT{ZIzdLUBdBChUWZD%??acY32?of`Rk|3G1U77$L+
z`92tPL)8M)kWP|w?BYm?ajkOi;E$e`$AkFmvn5oR#0oN~_hu#2CFF)BEB^_|YFpO@
zWU;EV2|K!sO8R(X>bIQ0uCa3J)6#Y9byn{L^wy`u5Uc*tZo+8w7oDilsEn&)spJyo
z{K?aArFdp#-AyF=STA+a-j&!0j%*p2wU;nMeDn>tQfEzN&&*{`&!tb5P6)?vBTSGc
z_~l+7fKB%}`91d;x}WdR13P``_)`q)RlOU(`4S$V`I4|(M1K`t^)@J4wh;6E0256W
zJRNgjn_Bp}qrzVAEMmYO3(Buz%p9MMoFSfB?955UkG839EB%CD_Q2BsD$t1BfpNIT
zZDy|FAH-=y2R2jFPGt5yW&K>uTBiu;J@;3n(WzpwFp%lxm*tcxlv7fUX-o?fK(|Q9
zS$^Z~-)A#PH*N%d#OL3e4fx9J6zZ??XZf3Uv1&^X5g!We0ftB$3{iLtmTJN<C$G`Q
zHix76qlKXX#0p$RL%XuhwGq){)6OIBOX4`L&6PXzIE9rhQ}R>1lthc!i)m7_iue at 1
zKo!*G&EvW|!R;eCl~%1xrIm%Rk|_&$-x}-Xy=OLxvE at i90cI4GFqRZ>HDo1`8($*`
zDJq%XVgm7pK|A at y3@rL{)ROn{%a8ABr`iKqKtQQFD><DERbiuB6^r0(hgoNy7PaIJ
z`a12|=%v?2j!1j!xsSfcbd;*9lj~X&vZV2Y+OB`M`}5~E4pC5{dbP|5FaMI at g3PRQ
zEf1II;$Ienl0fyl6{(!?KH*?yvJ;dRo0q6x^1F?1jxqcVltusQOq;X-;qB at Tt+Ej+
z6FV#u#jjtRZhsQ at -fH~P5zE#<LRwY(Wb`&&*ly&0!*Q-9aEe7<8x9-YFeiSuUBqG%
zC{(mzlW}OXHdDezvf{DSuH!e-C?aQYvs?MuKA3Zo?i$Ipw&C0zZ4y{h7_e|Iss<UA
z_Z5}G^Q6Re&)9o<YJc;D(1M>V&B+LEJpU(_sr6s5qD4Tsc+=QlhiCK~+0hM#oPK%5
z+L(QkA660_BOg0+ra3ptNhrxjI0_B3_J=1q5BlY!eC8cjUM$U)F9?*4Y+U{wsThNv
zFScj~c4yY2=r|$|p~@cw at F>9~Wl_B6n#p<pvdS5rjn5_(xI*^MpexkKAMdN)AS_)!
zDk^PV&iU#GQ+s$Y$Q5$F|80fIeYsH?s?gnI>T~ypi6SDlgeRq0cvL0=bBbJ6&z#|1
zf5;g`Df~ZNHV%6&pWwnDq{g|6(_s{BjoiU<(IqTtNnhN;$eAn2VBx at JA_!wji1Z8i
zD5180)HFI7-RGmtw~<9OaW1xQ=%mycv-x2WED(ld7=`TA<uD~NNZ$1I_KReSh<d)}
zkR)6gZD23<@Mi|HfZWZ#FgjL1a*t&gEz|zbRAxegI%*%s)e4J9c_2hOX^MO&G*1*P
zDjZQ`rF^?orjbYGq5~}bxG*qo#`Zpr3S=~r*4pl6me;S)JU!mt?!1-9J>E*2?L=|g
zu1wRE!nno0 at m7!>+?vA3(*_K!a=3C-8_T>Jp%O40Eq_p~rQ$F#j%8-qol|hV%t6%r
z3)k at JHJ2(pD;=a{(6O7cm~jLKlk!7Ly{r9-+)O;IJc at s32;Q4~$cv3hXkIRr*Yzo<
zeg3_IH-BKZ5Z&Q()<X1j_aQC*!j{xMyXXOYo<WeNkB2SBZhXRql{wREAY?oJ<kiJG
zSO}~0{=spsjn%yzkBx{<=Uco^x{aYRir<5{8^O6KZ~cTJP}W+KNN;9$6*%YnE~DDk
zCNOxs^2Vbdg6E>4kc(k6)KOpoFXlAn{X4^Po(5Izph>03*p5&=jw;gCygc?-0)>Z|
zokr!U_E68r!r4irS<kgFM7SL>g0okMp}zS;x?*rPf~fDiNj^&GO4VU#YtA;ZKaPA1
zghyU<BPUyTdKJkQC1 at L}$DJ}CQu^f_?bTa({H^duJMJ6>O~*&{ut_V>iu!h4perQQ
zN&xRBMpt5t&t7WnuQZ~gX_9_Cd6>B<i}wfdcNmiplDmY4+_N?iy-Pi5+xfSP2p3jh
zVAmuLc6zEcp0a-F;*c0k4MDS0^v4~!kL}cnf16w_=%4W>7c95wP`|4L!C=k6-n*nM
z1>G8)XzwpJ_W$ni{>4iT_iXOYQEO`|(ELVA2%?<${!yaTOe5Nr=)V at 4+4#18sQ$(Y
zlr8!{kf)e&B4uP<d8oTsj&>B{-#;%606?fQh{EQoQ|oa_0X at MXeIXtk0wlN?U{Kl!
z=V%gIk0t<3kpaLW05E>pj3$vP;I at vG)i?J9;#L#Dg4M?C%#>*UN{j*cr%;F8s6!OW
z`T54-+y8@}wO%Os&nC0kuy!tZg7EQe2*=gP6UNJz>~LY6ptL}4rKcjFC|7 at R`iknG
z#N%~`^_RVQL1AbsC&JHY!1dL?T4&PxE^=@Y<C*ghCuTM3-c&(!Un*vbiAvtjE2K(_
z%vBvD)gw2|FCo9$W)k|C6<4H%n+{G+bS)m#tBL*OI5&65)8#;^?(BqYDs~sNJQm90
zG`wnq417vjg0-1s<Oww&>NPc4o**tXh9slOLAhZPNg2gm9qnOX)L*#$xy#U<iiCtJ
z3 at 7^&YA4iQ?fk-egA<PRyKz9A2S at g;PbZ&%s=t$`cE0GjFbC55oR at 4Ulz<uXb*(Eq
z9S$z=Brz at H#gW={JQpAhX+L+675wTtL3!FQ^5@)^mBX8wD^?MA!lOcikam8>Z&k8#
zBK`d=pi+IErc)SJc~bu*_jLiDeW)=1q#sewp(1eNaE;1Zy=_T_Mo-0_D_hbhr)r9O
zl5}@Fe|<y0bvvV at 8o1E0JIKKMQGA^2&sXQ|LsUd2-kiJF%Sqh1TLa_78?Ej-$&*Nv
zwW>JlN*(M*LQOp*pB%oX$%T5FpJM^h_-|!nhV+RB*vh0Z7x<6`sQ0CE*;VkRpqWSn
zeui|KExtw`GeP^6PkGrisxaz2H)4+7Mh}?9SWeTpbb9P0Tc_k(hnb`-y;b<#Rb^!g
zyAdQ4&-~I5qhT-`#1o>=zq#aT^+*zOp%-v9qs~5f8NnE{v&nHLHT4EZTH}gNo^YQe
zq;f6*18ahz-Iu~CISHhk2z_a)s3|V-*|AxMZUkvDZB(zI+4d_U7FLYKeH#!uk;TMU
zMRd4>fyPYaoU!OXuauvOmMS^^gMp+<QG&du;%OT-&{3aN$92d!Q}^BDE80~YPkQ`W
zOo{BkrojMwL-4DPjrzOYomWIz=?jYuRn2sHos-JWr4z(HEU_UxxgpaxNVLpc2Xy{C
z=i_(e`wXH=^uj)eIP8M{unv2t54xD$4bsMrz6tYPq7`$Um!o(Ggtf#&rL$xSI%SRb
zn+1r$>Gv6r8Z8nS(9=RfQ&@n!x$0|OS>Ux=Ca;;AqyrV{<j+AO38~*zu1Df_Dxx1u
z;R>&}6_KuC>rP at 8hwX8VDO98=HLpekH5x6afKXe*8w0q>)Mp(71d7o{qW4sT?C892
zwuIHU5U`3cDlow6RX_a3bL5jNBdMmy=RH<?K9Cm{Z=QSc{Q(zs8WY|ls>)S*r;1!T
zGRyA0E-=~~*7E<#<JiJ*wN+2!>>1_SU3uhl at P_V0XbN0r`awMM*yS7S8o?-Iq+c*G
z at TOpjT@{DcYrn3sYLkE3E at l>Uw<F#Cie$*Wg{B!xcc1gz?d49E`+z{)WVz>_oTx{+
zR+TE}7a<&-{wwZH8m`cWD!&+3{=KL~MKSNg?m&u9eBQl~0Le`SwB5Je(CRQ?akw;`
zLw_(P=PM5A1K+28V-bue^oDYpzREO4J=^HW>QCZ3b3Hp5^pgTfIs)-{&pXgOz!Z&%
zRf?hL;DLC53tKbBY!?DJGlTwE5qvB?NUIxPG($6q{hiOJ#m3k9=c{Aj-UueD*iNtG
zDm$C`#R-k`ZJzkRF<YCCm%m>QxG(&MoF5<cb1S)15OULU8}z7TsTt9VFFa;$GUJKn
z-XK;Imj(n at KOR^Zpv9_t{26?+o9Vt+ at -?iTr@=~4o2EJ|0CrWCo#;U*D~OJKpMfbN
z7pM?xL_EBK4gMH}0esNB5?W@$Rl9k1Vpr6Tk%>)TZPpG~=NGDyc||UdLoh>vP}Doo
z2%?-d0!a1z#XtW+ZZUXvNdC0>=P%~n9};%U$6cUk at 6l4o<8{nSOL40hde;k;e&|$Q
zVRle0%zYcvYOUNP%bHq;doGFC!kCROj8~Kzk(~R5F`xxLKt(6AO(6cnvNOJ)Xj|6e
z)r#SmPXBEgZg{ennlnriVrLt+xqDS at e&%t(`po>R=yCR?g!8(LKE}R`PZo6q*l)}*
zeLO&tE(y9xoZxm{wc)4Wf;ZIkaV)P!l>JS6#AnSFl8dRp2i4C`L)ZmEi|bol*S768
z+=m44GrJ0lZ?9$gW{A%#+3_Q(l%7=(=2usR&&1@>M- at +85Ppvv?Prpoa{>2b-Q%pf
z812F9WGz+&^6*q(PfZ}w#>wtk at ZQC{+MR~BrB|t1{kK^sfKqExK)RYj7AUXgjDuyW
z5x5^1!Za+|tbxg_VPm!(ctO<v`RW-Xl)Z at EhaN^`m3KcG5=`7D_0M!*Bi^p1cIeL$
z`o}~^j0Ws$kqX%U5g|%}0%IxizF}5+_KFb2P8f0|bC)&C;BkTd%*^~aUKG^wKy6^e
zBLtWSzk5hgn^cHEJYA#)Ki_p0x-v-q{?8IbTRbSUs}w|Vn+IAQ+N1n>ob{wU{4AbV
zu9A49frZ+;j5(6_Nm~J5f;;`75Pl2;eV--p^YmlkNJ^_Xqs8Xm{#cwl90uE*Jf}!u
zzkzrgaZj8LVIRtoOD!*yhOIApN-}@k at 1sw<&}6r4GM#?pbKHCwhA-Wgg%wz5CH at r~
zpL5ljt0cjIn1RL5sIAbHbjABm9v)`a2^1v1NXf$nlQG<4cpD^h0;xwBY2OgaG;x}<
zv7Fgoe7m1qw45y{&XT!m_42zP${6}tq}nEPiz4geFEJ%~DhpF1>4Ug+$wv^yYThTJ
z8lI>;7+#mL#?*ZJ2fN at a2JLFrw0EEAQB8Yb4+c$D6*40c`X|c=@V>OB`acl+2X$i$
z&aqBzwTrgqf at r}4?-ceIZj$#d*+`f<z-c`-X@@ee;=@%VK2r~E4#(RaV?SwTOC~uR
zxDrK0(B^~+P@>{Q)6z7fP<raLf1_#dCBDZA#fufhD4!d!LA>w|u%NiDJuD(3Aut_J
zB$WeI>SgZg_EAl=Nm-}NBCzS>52hp25`1v8 at LMMC%)UO%)66y%8ajuLUw+}_jf<6q
zzd_dT1Aj!lt%J$X*O}?#X!1F)`68aJ4C{SKDw5L(4!~DT*gxt5|NG9g^nrTv+{i1W
ze=F+NYQ21UXnfT4$3=S2V+>lm-=xj&*WjC~dt-)QzF1hL9)OM!yUG(CT~#(6AI`}7
zu7#Ysy4LY87mqe3*1v)k$a47X81nU`ycYhO+>vqUJz2JOnJsmEd-Li_;8z;kk=FEi
zn>npn1}!y4!}lJIpv6bE(y&;?h-lUY+_$w0F8j&^#N|}j9$G+#`Q*^%EollIMyvcx
z<H3Ai_E^fMKZn3!%LXZ_PbTB!)Gxn^K66K?<3-vP5>Fsb{Sz&g=2w3S4GVr9Psih$
z3FamP^mw at yI(_O<fB_8lNQ>IiCtrXkAw(`#dl^D$1)JlpsectmRh{e-kev$J2sah?
z)n5`R{HaC<U^~v83zZ3>h(hNf{wCJqZztG>>B{wJTQtJj+DhM4MK)XcaIO#bTuJI9
R`4aDV?4_>I=7?&J{|DXTQmz01

diff --git a/src/box/lua/space.cc b/src/box/lua/space.cc
index f6e96f0..01b58af 100644
--- a/src/box/lua/space.cc
+++ b/src/box/lua/space.cc
@@ -653,6 +653,8 @@ box_lua_space_init(struct lua_State *L)
 	lua_setfield(L, -2, "SPACE_SEQUENCE_ID");
 	lua_pushnumber(L, BOX_FUNC_INDEX_ID);
 	lua_setfield(L, -2, "FUNC_INDEX_ID");
+	lua_pushnumber(L, BOX_SESSION_SETTINGS_ID);
+	lua_setfield(L, -2, "SESSION_SETTINGS_ID");
 	lua_pushnumber(L, BOX_SYSTEM_ID_MIN);
 	lua_setfield(L, -2, "SYSTEM_ID_MIN");
 	lua_pushnumber(L, BOX_SYSTEM_ID_MAX);
diff --git a/src/box/lua/upgrade.lua b/src/box/lua/upgrade.lua
index 07f1e03..4dfd571 100644
--- a/src/box/lua/upgrade.lua
+++ b/src/box/lua/upgrade.lua
@@ -951,8 +951,23 @@ local function drop_func_collation()
     _func.index.name:alter({parts = {{'name', 'string'}}})
 end
 
+local function create_session_settings_space()
+    local _space = box.space[box.schema.SPACE_ID]
+    local _index = box.space[box.schema.INDEX_ID]
+    local format = {}
+    format[1] = {name='name', type='string'}
+    format[2] = {name='value', type='any'}
+    log.info("create space _session_settings")
+    _space:insert{box.schema.SESSION_SETTINGS_ID, ADMIN, '_session_settings',
+                  'virtual', 2, {temporary = true}, format}
+    log.info("create index _session_settings:primary")
+    _index:insert{box.schema.SESSION_SETTINGS_ID, 0, 'primary', 'tree',
+                  {unique = true}, {{0, 'string'}}}
+end
+
 local function upgrade_to_2_3_1()
     drop_func_collation()
+    create_session_settings_space()
 end
 
 --------------------------------------------------------------------------------
diff --git a/src/box/schema_def.h b/src/box/schema_def.h
index ba870ff..f86cd42 100644
--- a/src/box/schema_def.h
+++ b/src/box/schema_def.h
@@ -114,6 +114,8 @@ enum {
 	BOX_CK_CONSTRAINT_ID = 364,
 	/** Space id of _func_index. */
 	BOX_FUNC_INDEX_ID = 372,
+	/** Space id of _session_settings. */
+	BOX_SESSION_SETTINGS_ID = 380,
 	/** End of the reserved range of system spaces. */
 	BOX_SYSTEM_ID_MAX = 511,
 	BOX_ID_NIL = 2147483647
@@ -277,6 +279,12 @@ enum {
 	BOX_FUNC_INDEX_FUNCTION_ID = 2,
 };
 
+/** _session_settings fields. */
+enum {
+	BOX_SESSION_SETTINGS_FIELD_NAME = 0,
+	BOX_SESSION_SETTINGS_FIELD_VALUE = 1,
+};
+
 /*
  * Different objects which can be subject to access
  * control.
diff --git a/src/box/session_settings.c b/src/box/session_settings.c
new file mode 100644
index 0000000..b5b5db8
--- /dev/null
+++ b/src/box/session_settings.c
@@ -0,0 +1,409 @@
+/*
+ * Copyright 2010-2019, Tarantool AUTHORS, please see AUTHORS file.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ *    copyright notice, this list of conditions and the
+ *    following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer in the documentation and/or other materials
+ *    provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "session_settings.h"
+#include "xrow_update.h"
+#include "virtual_engine.h"
+#include "session.h"
+#include "schema.h"
+#include "tuple.h"
+#include "xrow.h"
+#include "sql.h"
+
+struct session_settings_modules
+	session_settings_modules[SESSION_SETTING_MODULE_max] = {};
+
+struct session_settings_index {
+	/** Base index. Must be the first member. */
+	struct index base;
+	/** Format to create tuples on the fly. */
+	struct tuple_format *format;
+};
+
+struct session_settings_iterator {
+	/** Base iterator. Must be the first member. */
+	struct iterator base;
+	/** Format of the tuples this iterator returns. */
+	struct tuple_format *format;
+	/** ID of current module in global list of the modules. */
+	int module_id;
+	/** ID of the setting in current module. */
+	int current_id;
+	/** Decoded key. */
+	char *key;
+	/** Type of iterator. */
+	enum iterator_type iterator_type;
+};
+
+static void
+session_settings_iterator_free(struct iterator *ptr)
+{
+	struct session_settings_iterator *it =
+		(struct session_settings_iterator *)ptr;
+	free(it->key);
+	free(it);
+}
+
+static int
+session_settings_iterator_next(struct iterator *iterator, struct tuple **result)
+{
+	struct session_settings_iterator *it =
+		(struct session_settings_iterator *)iterator;
+	if (it->module_id >= SESSION_SETTING_MODULE_max || it->module_id < 0) {
+		*result = NULL;
+		return 0;
+	}
+
+	struct tuple *ret = NULL;
+	int i = it->module_id;
+	int j = it->current_id;
+	enum iterator_type type = it->iterator_type;
+	struct tuple_format *format = it->format;
+	struct session_settings_modules *module;
+	const char *key = it->key;
+
+	if (!iterator_type_is_reverse(type)) {
+		for (; i < SESSION_SETTING_MODULE_max; ++i) {
+			module = &session_settings_modules[i];
+			if (module->get(format, j, key, type, &j, &ret) != 0)
+				return -1;
+			if (ret != NULL)
+				break;
+			j = 0;
+		}
+		*result = ret;
+		if (i == SESSION_SETTING_MODULE_max) {
+			it->module_id = SESSION_SETTING_MODULE_max;
+			it->current_id = 0;
+			return 0;
+		}
+		++j;
+		if (j >= (int)module->size) {
+			++i;
+			j = 0;
+		}
+		it->module_id = i;
+		it->current_id = j;
+		return 0;
+	}
+
+	for (; i >= 0; --i) {
+		module = &session_settings_modules[i];
+		if (module->get(format, j, key, type, &j, &ret) != 0)
+			return -1;
+		if (ret != NULL)
+			break;
+		if (i > 0)
+			j = session_settings_modules[i - 1].size - 1;
+	}
+	*result = ret;
+	if (i < 0) {
+		it->module_id = -1;
+		it->current_id = 0;
+		return 0;
+	}
+	--j;
+	if (j < 0) {
+		--i;
+		if (i >= 0)
+			j = module[i].size - 1;
+	}
+	it->module_id = i;
+	it->current_id = j;
+	return 0;
+}
+
+static void
+session_settings_index_destroy(struct index *index)
+{
+	free(index);
+}
+
+static struct iterator *
+session_settings_index_create_iterator(struct index *base,
+				       enum iterator_type type, const char *key,
+				       uint32_t part_count)
+{
+	struct session_settings_index *index =
+		(struct session_settings_index *)base;
+	char *decoded_key = NULL;
+	if (part_count > 0) {
+		assert(part_count == 1);
+		assert(mp_typeof(*key) == MP_STR);
+		uint32_t len;
+		const char *name = mp_decode_str(&key, &len);
+		decoded_key = (char *)malloc(len + 1);
+		if (decoded_key == NULL) {
+			diag_set(OutOfMemory, len + 1, "malloc", "decoded_key");
+			return NULL;
+		}
+		memcpy(decoded_key, name, len);
+		decoded_key[len] = '\0';
+	}
+	struct session_settings_iterator *it =
+		(struct session_settings_iterator *)malloc(sizeof(*it));
+	if (it == NULL) {
+		diag_set(OutOfMemory, sizeof(*it), "malloc", "it");
+		free(decoded_key);
+		return NULL;
+	}
+	iterator_create(&it->base, base);
+	it->base.next = session_settings_iterator_next;
+	it->base.free = session_settings_iterator_free;
+	it->key = decoded_key;
+	it->iterator_type = type;
+	it->format = index->format;
+	it->module_id = iterator_type_is_reverse(type) ?
+			SESSION_SETTING_MODULE_max - 1 : 0;
+	it->current_id = iterator_type_is_reverse(type) ?
+			 session_settings_modules[it->module_id].size - 1 : 0;
+	return (struct iterator *)it;
+}
+
+static int
+session_settings_index_get(struct index *base, const char *key,
+			   uint32_t part_count, struct tuple **result)
+{
+	struct session_settings_index *index =
+		(struct session_settings_index *)base;
+	assert(part_count == 1);
+	(void)part_count;
+	uint32_t len;
+	const char *tmp = mp_decode_str(&key, &len);
+	const char *decoded_key = tt_cstr(tmp, len);
+	struct tuple *ret = NULL;
+	struct tuple_format *format = index->format;
+	for (int i = 0; i < SESSION_SETTING_MODULE_max; ++i) {
+		if (session_settings_modules[i].get(format, 0, decoded_key,
+						    ITER_EQ, NULL, &ret) != 0)
+			return -1;
+		if (ret != NULL)
+			break;
+	}
+	*result = ret;
+	return 0;
+}
+
+static const struct index_vtab session_settings_index_vtab = {
+	/* .destroy = */ session_settings_index_destroy,
+	/* .commit_create = */ generic_index_commit_create,
+	/* .abort_create = */ generic_index_abort_create,
+	/* .commit_modify = */ generic_index_commit_modify,
+	/* .commit_drop = */ generic_index_commit_drop,
+	/* .update_def = */ generic_index_update_def,
+	/* .depends_on_pk = */ generic_index_depends_on_pk,
+	/* .def_change_requires_rebuild = */
+		generic_index_def_change_requires_rebuild,
+	/* .size = */ generic_index_size,
+	/* .bsize = */ generic_index_bsize,
+	/* .min = */ generic_index_min,
+	/* .max = */ generic_index_max,
+	/* .random = */ generic_index_random,
+	/* .count = */ generic_index_count,
+	/* .get = */ session_settings_index_get,
+	/* .replace = */ generic_index_replace,
+	/* .create_iterator = */ session_settings_index_create_iterator,
+	/* .create_snapshot_iterator = */
+		generic_index_create_snapshot_iterator,
+	/* .stat = */ generic_index_stat,
+	/* .compact = */ generic_index_compact,
+	/* .reset_stat = */ generic_index_reset_stat,
+	/* .begin_build = */ generic_index_begin_build,
+	/* .reserve = */ generic_index_reserve,
+	/* .build_next = */ generic_index_build_next,
+	/* .end_build = */ generic_index_end_build,
+};
+
+static void
+session_settings_space_destroy(struct space *space)
+{
+	free(space);
+}
+
+static int
+session_settings_space_execute_replace(struct space *space, struct txn *txn,
+				       struct request *request,
+				       struct tuple **result)
+{
+	(void)space;
+	(void)txn;
+	(void)request;
+	(void)result;
+	diag_set(ClientError, ER_UNSUPPORTED, "Session_settings space",
+		 "replace()");
+	return -1;
+}
+
+static int
+session_settings_space_execute_delete(struct space *space, struct txn *txn,
+				      struct request *request,
+				      struct tuple **result)
+{
+	(void)space;
+	(void)txn;
+	(void)request;
+	(void)result;
+	diag_set(ClientError, ER_UNSUPPORTED, "Session_settings space",
+		 "delete()");
+	return -1;
+}
+
+static int
+session_settings_space_execute_update(struct space *space, struct txn *txn,
+				      struct request *request,
+				      struct tuple **result)
+{
+	(void)txn;
+	const char *data = request->key;
+	uint32_t key_len = mp_decode_array(&data);
+	if (key_len == 0) {
+		diag_set(ClientError, ER_EXACT_MATCH, 1, 0);
+		return -1;
+	}
+	if (key_len > 1 || mp_typeof(*data) != MP_STR) {
+		diag_set(ClientError, ER_KEY_PART_TYPE, 0, "string");
+		return -1;
+	}
+	uint32_t len;
+	const char *tmp = mp_decode_str(&data, &len);
+	const char *decoded_key = tt_cstr(tmp, len);
+
+	int id;
+	struct tuple *old_tuple = NULL;
+	struct tuple_format *format = space->format;
+	struct session_settings_modules *module = NULL;
+	for (int i = 0; i < SESSION_SETTING_MODULE_max; ++i) {
+		module = &session_settings_modules[i];
+		if (module->get(format, 0, decoded_key, ITER_EQ, &id,
+				&old_tuple) != 0)
+			return -1;
+		if (old_tuple != NULL)
+			break;
+	}
+	if (old_tuple == NULL)
+		return 0;
+
+	uint32_t new_size = 0, bsize;
+	const char *old_data = tuple_data_range(old_tuple, &bsize);
+	const char *new_data =
+		xrow_update_execute(request->tuple,request->tuple_end,
+				    old_data, old_data + bsize, format->dict,
+				    &new_size, request->index_base, NULL);
+	if (new_data == NULL)
+		return -1;
+
+	uint32_t array_len = mp_decode_array(&new_data);
+	if (array_len != 2)
+		if (format->exact_field_count != array_len) {
+		diag_set(ClientError, ER_EXACT_FIELD_COUNT,
+			 array_len, format->exact_field_count);
+		return -1;
+	}
+
+	if (mp_typeof(*new_data) != MP_STR) {
+		diag_set(ClientError, ER_CANT_UPDATE_PRIMARY_KEY,
+			 space_index(space, 0)->def->name, space_name(space));
+		return -1;
+	}
+
+	const char *value = new_data;
+	mp_next(&value);
+	mp_decode_array(&old_data);
+	uint32_t size_a = mp_sizeof_str(len);
+	uint32_t size_b = value - new_data;
+	if (size_a != size_b || memcmp(old_data, new_data, size_a) != 0) {
+		diag_set(ClientError, ER_CANT_UPDATE_PRIMARY_KEY,
+			 space_index(space, 0)->def->name, space_name(space));
+		return -1;
+	}
+
+	return module->set(format, id, value, result);
+}
+
+static int
+session_settings_space_execute_upsert(struct space *space, struct txn *txn,
+				      struct request *request)
+{
+	(void)space;
+	(void)txn;
+	(void)request;
+	diag_set(ClientError, ER_UNSUPPORTED, "Session_settings space",
+		 "upsert()");
+	return -1;
+}
+
+static struct index *
+session_settings_space_create_index(struct space *space, struct index_def *def)
+{
+	assert(space->def->id == BOX_SESSION_SETTINGS_ID);
+	if (def->iid != 0) {
+		diag_set(ClientError, ER_UNSUPPORTED, "Session_settings space",
+			 "create_index()");
+		return NULL;
+	}
+
+	struct session_settings_index *index =
+		(struct session_settings_index *)calloc(1, sizeof(*index));
+	if (index == NULL) {
+		diag_set(OutOfMemory, sizeof(*index), "calloc", "index");
+		return NULL;
+	}
+	if (index_create(&index->base, space->engine,
+			 &session_settings_index_vtab, def) != 0) {
+		free(index);
+		return NULL;
+	}
+
+	index->format = space->format;
+	return &index->base;
+}
+
+const struct space_vtab session_settings_space_vtab = {
+	/* .destroy = */ session_settings_space_destroy,
+	/* .bsize = */ generic_space_bsize,
+	/* .execute_replace = */ session_settings_space_execute_replace,
+	/* .execute_delete = */ session_settings_space_execute_delete,
+	/* .execute_update = */ session_settings_space_execute_update,
+	/* .execute_upsert = */ session_settings_space_execute_upsert,
+	/* .ephemeral_replace = */ generic_space_ephemeral_replace,
+	/* .ephemeral_delete = */ generic_space_ephemeral_delete,
+	/* .ephemeral_rowid_next = */ generic_space_ephemeral_rowid_next,
+	/* .init_system_space = */ generic_init_system_space,
+	/* .init_ephemeral_space = */ generic_init_ephemeral_space,
+	/* .check_index_def = */ generic_space_check_index_def,
+	/* .create_index = */ session_settings_space_create_index,
+	/* .add_primary_key = */ generic_space_add_primary_key,
+	/* .drop_primary_key = */ generic_space_drop_primary_key,
+	/* .check_format = */ generic_space_check_format,
+	/* .build_index = */ generic_space_build_index,
+	/* .swap_index = */ generic_space_swap_index,
+	/* .prepare_alter = */ generic_space_prepare_alter,
+	/* .invalidate = */ generic_space_invalidate,
+};
diff --git a/src/box/session_settings.h b/src/box/session_settings.h
new file mode 100644
index 0000000..e7ecbdb
--- /dev/null
+++ b/src/box/session_settings.h
@@ -0,0 +1,61 @@
+#pragma once
+/*
+ * Copyright 2010-2019, Tarantool AUTHORS, please see AUTHORS file.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ *    copyright notice, this list of conditions and the
+ *    following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer in the documentation and/or other materials
+ *    provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include <stddef.h>
+#include <stdint.h>
+#include "iterator_type.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif /* defined(__cplusplus) */
+
+enum session_setting_module {
+	SESSION_SETTING_MODULE_max
+};
+
+struct tuple;
+struct tuple_format;
+
+struct session_settings_modules {
+	enum session_setting_module id;
+	uint32_t size;
+	int (*get)(struct tuple_format *format, int id, const char *key,
+		   enum iterator_type type, int *end_id, struct tuple **result);
+	int (*set)(struct tuple_format *format, int id, const char *value,
+		   struct tuple **result);
+};
+
+extern struct session_settings_modules session_settings_modules[];
+extern const struct space_vtab session_settings_space_vtab;
+
+#if defined(__cplusplus)
+} /* extern "C" */
+#endif /* defined(__plusplus) */
diff --git a/src/box/virtual_engine.c b/src/box/virtual_engine.c
index 45993b9..8680747 100644
--- a/src/box/virtual_engine.c
+++ b/src/box/virtual_engine.c
@@ -28,6 +28,7 @@
  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
+#include "session_settings.h"
 #include "virtual_engine.h"
 #include "schema.h"
 #include "tuple.h"
@@ -42,13 +43,50 @@ static struct space *
 virtual_engine_create_space(struct engine *engine, struct space_def *def,
 			    struct rlist *key_list)
 {
-	(void)engine;
-	(void)def;
-	(void)key_list;
-	/* There are currently no spaces with this engine. */
-	diag_set(ClientError, ER_UNSUPPORTED, "Tarantool",
-		 "spaces with this engine.");
-	return NULL;
+	/*
+	 * At the moment the only space that have this engine is
+	 * _session_sessings.
+	 */
+	if (def->id != BOX_SESSION_SETTINGS_ID) {
+		diag_set(ClientError, ER_UNSUPPORTED, "Tarantool",
+			 "non-system space with this engine.");
+		return NULL;
+	}
+	const struct space_vtab *space_vtab = &session_settings_space_vtab;
+
+	struct space *space = (struct space *)calloc(1, sizeof(*space));
+	if (space == NULL) {
+		diag_set(OutOfMemory, sizeof(*space), "calloc", "space");
+		return NULL;
+	}
+	int key_count = 0;
+	struct key_def **keys = index_def_to_key_def(key_list, &key_count);
+	if (keys == NULL) {
+		free(space);
+		return NULL;
+	}
+	struct tuple_format *format =
+		tuple_format_new(&tuple_format_runtime->vtab, NULL, keys,
+				 key_count, def->fields, def->field_count,
+				 def->exact_field_count, def->dict,
+				 def->opts.is_temporary,
+				 def->opts.is_ephemeral);
+	if (format == NULL) {
+		free(space);
+		return NULL;
+	}
+	tuple_format_ref(format);
+	int rc = space_create(space, engine, space_vtab, def, key_list, format);
+	/*
+	 * Format is now referenced by the space if space has beed
+	 * created.
+	 */
+	tuple_format_unref(format);
+	if (rc != 0) {
+		free(space);
+		return NULL;
+	}
+	return space;
 }
 
 static const struct engine_vtab virtual_engine_vtab = {
diff --git a/test/app-tap/tarantoolctl.test.lua b/test/app-tap/tarantoolctl.test.lua
index 7a07860..4d70595 100755
--- a/test/app-tap/tarantoolctl.test.lua
+++ b/test/app-tap/tarantoolctl.test.lua
@@ -415,8 +415,8 @@ do
             check_ctlcat_xlog(test_i, dir, "--from=3 --to=6 --format=json --show-system --replica 1", "\n", 3)
             check_ctlcat_xlog(test_i, dir, "--from=3 --to=6 --format=json --show-system --replica 1 --replica 2", "\n", 3)
             check_ctlcat_xlog(test_i, dir, "--from=3 --to=6 --format=json --show-system --replica 2", "\n", 0)
-            check_ctlcat_snap(test_i, dir, "--space=280", "---\n", 24)
-            check_ctlcat_snap(test_i, dir, "--space=288", "---\n", 52)
+            check_ctlcat_snap(test_i, dir, "--space=280", "---\n", 25)
+            check_ctlcat_snap(test_i, dir, "--space=288", "---\n", 53)
         end)
     end)
 
diff --git a/test/box-py/bootstrap.result b/test/box-py/bootstrap.result
index 938a763..f2ad75e 100644
--- a/test/box-py/bootstrap.result
+++ b/test/box-py/bootstrap.result
@@ -96,6 +96,8 @@ box.space._space:select{}
         'type': 'boolean'}]]
   - [372, 1, '_func_index', 'memtx', 0, {}, [{'name': 'space_id', 'type': 'unsigned'},
       {'name': 'index_id', 'type': 'unsigned'}, {'name': 'func_id', 'type': 'unsigned'}]]
+  - [380, 1, '_session_settings', 'virtual', 2, {'temporary': true}, [{'name': 'name',
+        'type': 'string'}, {'name': 'value', 'type': 'any'}]]
 ...
 box.space._index:select{}
 ---
@@ -153,6 +155,7 @@ box.space._index:select{}
   - [364, 0, 'primary', 'tree', {'unique': true}, [[0, 'unsigned'], [1, 'string']]]
   - [372, 0, 'primary', 'tree', {'unique': true}, [[0, 'unsigned'], [1, 'unsigned']]]
   - [372, 1, 'fid', 'tree', {'unique': false}, [[2, 'unsigned']]]
+  - [380, 0, 'primary', 'tree', {'unique': true}, [[0, 'string']]]
 ...
 box.space._user:select{}
 ---
diff --git a/test/box/access_sysview.result b/test/box/access_sysview.result
index 1f33dec..799d19f 100644
--- a/test/box/access_sysview.result
+++ b/test/box/access_sysview.result
@@ -246,11 +246,11 @@ box.session.su('guest')
 ...
 #box.space._vspace:select{}
 ---
-- 25
+- 26
 ...
 #box.space._vindex:select{}
 ---
-- 53
+- 54
 ...
 #box.space._vuser:select{}
 ---
@@ -282,7 +282,7 @@ box.session.su('guest')
 ...
 #box.space._vindex:select{}
 ---
-- 53
+- 54
 ...
 #box.space._vuser:select{}
 ---
diff --git a/test/box/alter.result b/test/box/alter.result
index 9a2f991..f150faa 100644
--- a/test/box/alter.result
+++ b/test/box/alter.result
@@ -92,7 +92,7 @@ space = box.space[t[1]]
 ...
 space.id
 ---
-- 373
+- 381
 ...
 space.field_count
 ---
@@ -137,7 +137,7 @@ space_deleted
 ...
 space:replace{0}
 ---
-- error: Space '373' does not exist
+- error: Space '381' does not exist
 ...
 _index:insert{_space.id, 0, 'primary', 'tree', {unique=true}, {{0, 'unsigned'}}}
 ---
@@ -220,6 +220,7 @@ _index:select{}
   - [364, 0, 'primary', 'tree', {'unique': true}, [[0, 'unsigned'], [1, 'string']]]
   - [372, 0, 'primary', 'tree', {'unique': true}, [[0, 'unsigned'], [1, 'unsigned']]]
   - [372, 1, 'fid', 'tree', {'unique': false}, [[2, 'unsigned']]]
+  - [380, 0, 'primary', 'tree', {'unique': true}, [[0, 'string']]]
 ...
 -- modify indexes of a system space
 _index:delete{_index.id, 0}
diff --git a/test/box/gh-4511-access-settings-from-any-frontend.result b/test/box/gh-4511-access-settings-from-any-frontend.result
index 9874616..75d53cf 100644
--- a/test/box/gh-4511-access-settings-from-any-frontend.result
+++ b/test/box/gh-4511-access-settings-from-any-frontend.result
@@ -6,5 +6,111 @@ test_run = require('test_run').new()
 -- User cannot create spaces with this engine.
 s = box.schema.space.create('test', {engine = 'virtual'})
  | ---
- | - error: Tarantool does not support spaces with this engine.
+ | - error: Tarantool does not support non-system space with this engine.
+ | ...
+
+-- Check _session_settings space.
+s = box.space._session_settings
+ | ---
+ | ...
+s:format()
+ | ---
+ | - [{'name': 'name', 'type': 'string'}, {'name': 'value', 'type': 'any'}]
+ | ...
+
+-- Make sure that we cannot drop space.
+s:drop()
+ | ---
+ | - error: Can't drop the primary key in a system space, space '_session_settings'
+ | ...
+
+--
+-- Make sure, that session_settings space doesn't support
+-- create_index(), insert(), replace() and delete() methods.
+--
+s:create_index('a')
+ | ---
+ | - error: Session_settings space does not support create_index()
+ | ...
+s:insert({'a', 1})
+ | ---
+ | - error: Session_settings space does not support replace()
+ | ...
+s:delete({'b'})
+ | ---
+ | - error: Session_settings space does not support delete()
+ | ...
+s:replace({'sql_defer_foreign_keys', true})
+ | ---
+ | - error: Session_settings space does not support replace()
+ | ...
+
+-- Check get() and select(). They should return nothing for now.
+s:get({'a'})
+ | ---
+ | ...
+s:select()
+ | ---
+ | - []
+ | ...
+s:select({}, {iterator='EQ'})
+ | ---
+ | - []
+ | ...
+s:select({}, {iterator='ALL'})
+ | ---
+ | - []
+ | ...
+s:select({}, {iterator='GE'})
+ | ---
+ | - []
+ | ...
+s:select({}, {iterator='GT'})
+ | ---
+ | - []
+ | ...
+s:select({}, {iterator='REQ'})
+ | ---
+ | - []
+ | ...
+s:select({}, {iterator='LE'})
+ | ---
+ | - []
+ | ...
+s:select({}, {iterator='LT'})
+ | ---
+ | - []
+ | ...
+s:select({'a'}, {iterator='EQ'})
+ | ---
+ | - []
+ | ...
+s:select({'a'}, {iterator='ALL'})
+ | ---
+ | - []
+ | ...
+s:select({'a'}, {iterator='GE'})
+ | ---
+ | - []
+ | ...
+s:select({'a'}, {iterator='GT'})
+ | ---
+ | - []
+ | ...
+s:select({'a'}, {iterator='REQ'})
+ | ---
+ | - []
+ | ...
+s:select({'a'}, {iterator='LE'})
+ | ---
+ | - []
+ | ...
+s:select({'a'}, {iterator='LT'})
+ | ---
+ | - []
+ | ...
+
+-- Currently there is nothing to update, but update() should work.
+s:update('some_option', {{'=', 'value', true}})
+ | ---
  | ...
diff --git a/test/box/gh-4511-access-settings-from-any-frontend.test.lua b/test/box/gh-4511-access-settings-from-any-frontend.test.lua
index 611caef..3304454 100644
--- a/test/box/gh-4511-access-settings-from-any-frontend.test.lua
+++ b/test/box/gh-4511-access-settings-from-any-frontend.test.lua
@@ -2,3 +2,40 @@ test_run = require('test_run').new()
 
 -- User cannot create spaces with this engine.
 s = box.schema.space.create('test', {engine = 'virtual'})
+
+-- Check _session_settings space.
+s = box.space._session_settings
+s:format()
+
+-- Make sure that we cannot drop space.
+s:drop()
+
+--
+-- Make sure, that session_settings space doesn't support
+-- create_index(), insert(), replace() and delete() methods.
+--
+s:create_index('a')
+s:insert({'a', 1})
+s:delete({'b'})
+s:replace({'sql_defer_foreign_keys', true})
+
+-- Check get() and select(). They should return nothing for now.
+s:get({'a'})
+s:select()
+s:select({}, {iterator='EQ'})
+s:select({}, {iterator='ALL'})
+s:select({}, {iterator='GE'})
+s:select({}, {iterator='GT'})
+s:select({}, {iterator='REQ'})
+s:select({}, {iterator='LE'})
+s:select({}, {iterator='LT'})
+s:select({'a'}, {iterator='EQ'})
+s:select({'a'}, {iterator='ALL'})
+s:select({'a'}, {iterator='GE'})
+s:select({'a'}, {iterator='GT'})
+s:select({'a'}, {iterator='REQ'})
+s:select({'a'}, {iterator='LE'})
+s:select({'a'}, {iterator='LT'})
+
+-- Currently there is nothing to update, but update() should work.
+s:update('some_option', {{'=', 'value', true}})
diff --git a/test/wal_off/alter.result b/test/wal_off/alter.result
index 62cb11d..97f7e6f 100644
--- a/test/wal_off/alter.result
+++ b/test/wal_off/alter.result
@@ -28,7 +28,7 @@ end;
 ...
 #spaces;
 ---
-- 65502
+- 65501
 ...
 -- cleanup
 for k, v in pairs(spaces) do
-- 
2.7.4



More information about the Tarantool-patches mailing list