From 1e510fd08a29dd76114d60c050a54043903a346c Mon Sep 17 00:00:00 2001 From: Stas Kelvich Date: Fri, 6 Nov 2015 03:01:56 +0300 Subject: [PATCH 01/46] Deploy pg from our repo --- tests/deploy/roles/postgres/tasks/main.yml | 116 +++++++++------------ tests/deploy/roles/postgres/vars/main.yml | 6 +- tests/deploy/tsdm.yml | 17 +-- 3 files changed, 65 insertions(+), 74 deletions(-) diff --git a/tests/deploy/roles/postgres/tasks/main.yml b/tests/deploy/roles/postgres/tasks/main.yml index 8e6660d..517dbd9 100644 --- a/tests/deploy/roles/postgres/tasks/main.yml +++ b/tests/deploy/roles/postgres/tasks/main.yml @@ -31,79 +31,65 @@ sudo: yes - name: clone postgres sources - git: repo=git://git.postgresql.org/git/postgresql.git + git: repo={{pg_repo}} dest={{pg_src}} version={{pg_version_tag}} - force=yes - update=yes depth=1 accept_hostkey=True register: pg_sources -- name: upload patches - get_url: "url={{pg_patch}} dest={{pg_src}}/p1.patch" - # when: pg_sources.before != pg_sources.after - -- name: patch postgres - patch: > - src={{pg_src}}/p1.patch - basedir={{pg_src}} - remote_src=True - strip=1 - - ############################################################################# -# - stat: path={{pg_datadir}}/postmaster.pid -# register: pg_pidfile - -# - name: stop postgres if it was running -# command: "{{pg_dst}}/bin/pg_ctl stop -w -D {{pg_datadir}}" -# when: pg_pidfile.stat.exists - -# - name: force rebuild on changed sources -# command: "rm {{pg_dst}}/bin/postgres" -# when: pg_sources.changed - -# - name: build and install -# shell: ./configure --prefix={{pg_dst}} --without-zlib && make clean && make -j {{makejobs}} && make install -# args: -# chdir: "{{pg_src}}" -# creates: "{{pg_dst}}/bin/postgres" - -# - name: remove datadirs on datanodes -# command: "rm -rf {{pg_datadir}}" -# when: pg_destroy_and_init - -# - name: create datadirs on datanodes -# command: "{{pg_dst}}/bin/initdb {{pg_datadir}}" -# args: -# creates: "{{pg_datadir}}" - -# - name: configure postgres on datanodes -# lineinfile: -# dest: "{{pg_datadir}}/postgresql.conf" -# line: "{{item.line}}" -# state: present -# with_items: "{{pg_config}}" - -# - name: configure postgres on datanodes -- 2 -# lineinfile: -# dest: "{{pg_datadir}}/postgresql.conf" -# line: "{{item.line}}" -# state: present -# with_items: "{{pg_config_role}}" - -# - name: enable blind trust on datanodes -# lineinfile: -# dest: "{{pg_datadir}}/pg_hba.conf" -# line: "host all all 0.0.0.0/0 trust" - -# # - include: pg_shard.yml -# # when: deploy_pg_shard - -# - name: start postgrespro -# command: "{{pg_dst}}/bin/pg_ctl start -w -D {{pg_datadir}} -l {{pg_datadir}}/pg.log" +- stat: path={{pg_datadir}}/postmaster.pid + register: pg_pidfile + +- name: stop postgres if it was running + command: "{{pg_dst}}/bin/pg_ctl stop -w -D {{pg_datadir}}" + when: pg_pidfile.stat.exists + +- name: force rebuild on changed sources + command: "rm {{pg_dst}}/bin/postgres" + when: pg_sources.changed + +- name: build and install + shell: ./configure --prefix={{pg_dst}} --without-zlib && make clean && make -j {{makejobs}} && make install + args: + chdir: "{{pg_src}}" + creates: "{{pg_dst}}/bin/postgres" + +- name: remove datadirs on datanodes + command: "rm -rf {{pg_datadir}}" + when: pg_destroy_and_init + +- name: create datadirs on datanodes + command: "{{pg_dst}}/bin/initdb {{pg_datadir}}" + args: + creates: "{{pg_datadir}}" + +- name: configure postgres on datanodes + lineinfile: + dest: "{{pg_datadir}}/postgresql.conf" + line: "{{item.line}}" + state: present + with_items: "{{pg_config}}" + +- name: configure postgres on datanodes -- 2 + lineinfile: + dest: "{{pg_datadir}}/postgresql.conf" + line: "{{item.line}}" + state: present + with_items: "{{pg_config_role}}" + +- name: enable blind trust on datanodes + lineinfile: + dest: "{{pg_datadir}}/pg_hba.conf" + line: "host all all 0.0.0.0/0 trust" + +# - include: pg_shard.yml +# when: deploy_pg_shard + +- name: start postgrespro + command: "{{pg_dst}}/bin/pg_ctl start -w -D {{pg_datadir}} -l {{pg_datadir}}/pg.log" diff --git a/tests/deploy/roles/postgres/vars/main.yml b/tests/deploy/roles/postgres/vars/main.yml index 1fe0ff6..e3059ee 100644 --- a/tests/deploy/roles/postgres/vars/main.yml +++ b/tests/deploy/roles/postgres/vars/main.yml @@ -6,9 +6,13 @@ deploy_postgres: false deploy_dtm: false deploy_pg_shard: false +pg_repo: git://git.postgresql.org/git/postgresql.git +pg_version_tag: master + + pg_destroy_and_init: false -pg_version_tag: master + pg_port: 5432 pg_dtm_enable: false pg_dtm_host: "127.0.0.1" diff --git a/tests/deploy/tsdm.yml b/tests/deploy/tsdm.yml index 4e10236..e997e04 100644 --- a/tests/deploy/tsdm.yml +++ b/tests/deploy/tsdm.yml @@ -6,17 +6,17 @@ - role: postgres pg_port: 15432 - pg_version_tag: REL9_5_BETA1 + pg_repo: https://github.com/kelvich/postgresql.git + pg_version_tag: xtm_patched pg_destroy_and_init: true pg_datadir: ./postgrespro-data - pg_patch: https://raw.githubusercontent.com/postgrespro/pg_dtm/master/xtm.patch - role: postgres pg_port: 15433 - pg_version_tag: REL9_5_BETA1 + pg_repo: https://github.com/kelvich/postgresql.git + pg_version_tag: xtm_patched pg_destroy_and_init: true pg_datadir: ./postgrespro-data2 - pg_patch: https://raw.githubusercontent.com/postgrespro/pg_dtm/master/xtm.patch tasks: @@ -28,7 +28,7 @@ register: dtm_sources - name: build dtm - shell: "PG_CONFIG={{pg_dst}}/bin/pg_config && make clean && make -j {{makejobs}} install" + shell: "PG_CONFIG={{pg_dst}}/bin/pg_config make -j {{makejobs}} install" args: chdir: ./pg_tsdtm when: dtm_sources.changed @@ -40,7 +40,8 @@ line: "shared_preload_libraries = 'pg_dtm'" state: present - - name: start postgrespro - command: "{{pg_dst}}/bin/pg_ctl restart -w -D {{pg_datadir}} -l {{pg_datadir}}/pg.log" - + - name: restart postgrespro1 + command: "{{pg_dst}}/bin/pg_ctl restart -w -D ./postgrespro-data -l ./postgrespro-data/pg.log" + - name: restart postgrespro2 + command: "{{pg_dst}}/bin/pg_ctl restart -w -D ./postgrespro-data -l ./postgrespro-data/pg.log" From e9491d80156d1a16b74992bc4e07d2dfcff48604 Mon Sep 17 00:00:00 2001 From: Stas Kelvich Date: Fri, 6 Nov 2015 12:46:24 +0300 Subject: [PATCH 02/46] delete .so and .o --- pg_dtm.o | Bin 53712 -> 0 bytes pg_dtm.so | Bin 25956 -> 0 bytes 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 pg_dtm.o delete mode 100755 pg_dtm.so diff --git a/pg_dtm.o b/pg_dtm.o deleted file mode 100644 index 519cd7cdb2f0e1e33ed59e723b20a74fcf7f591c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 53712 zcmce933yaR*7m)(b2|yi?F2~Jp&G&xc2H1M&;$}lAS^=yMns!V(n(sfnRM6$WfO^r zqB8E=%(#yWj*f~euDFYi3+}j};5Z{XE;usszi(CDPInTV`R4ndub-#xsdMVosZ&*_ z)_c3^)qno&mqf!bJq8|d32+7ohMyk8=n1#cE4>{)dfctZe#XIX&Rq%;rOQyL5eP&= z%OV;92n0&6v ztjWR-8c_S7oIj4?Ru&7+Ym}iIbYU&kZTY2YgiirvD zEtkaOz&e!I7_6%bHMP(0|6E>8I1*|M){H$yCfwFuwrKtQTCHu+Pui}=b+KxU`e=C* z6sfJeZCYNEjljGZJX7TNbi5dJythzYn5*M<`O8 z`Uq7ADjQL|DzL5nmENM|==xoTaf9;QUy5N=yM98}TRJ@{o%ocU4~L2#&lm>HGW$it zxD~Px&zJ+p-yrQchMfqP1@}Mw%`0fxTU@a2tAc_}GUux&7-{Fyx1SlkN<_%0D z0Z`_)03JCa(&I;fK~FY4EvJ2#*K*o{yq0-iDK(UWI;Db5=>;vBGD1sI!MdjlPCf0Z zG?8O4Kgdq{gT}g?PA$(C?94yt2Uo$SRR?uu@(&hlf?M}=`e{#9ZjttVZmi*x1Z&aFC&u}GQYqCk^xu7KpOmX3xWl>Tg#sB{sU-y;2K*=mh zTV^7@SYFzQ{AL}wSl(zYmewL4_HPPlceHSJ%feZ;Po|8D-GdM~*5Nc3o-WF0>B-=A zPmj^&+s1y;K4kvl3}=<9o3T4o)9A=vbTzKo$#UqR5O$u2LOA-!g%D#KV_%OqjA-lJ zhvJc<)6V6TwqWz5KSC-DZ>t2EBe7 zA><~Z47E+Rnx3|@G?AycAlI^ZVj2|`i<)~(f9C4!tt^O$vyt|em#;+j zQX==G#I`Sp6DiAc(@d0gtR=PN?}{yR*$m^x2iaduS_63x=1fjA&_QmNJxuO{yJ!@f zrHK@&A+=zqJrKkM2JEys72$YU)Z%cWU(hl>M}k)hTG+9@Pyn-5HnDlq2*}Ts3FO75 zfKE9+g(8)BL5mGhOoZvN@#yq2;4Ny&WO_(8hXF0)3nXB&$UKu()<5=#0zE3~K6A6` z`L*np;|n&K1@;ZBdp)|KfnTuBFdp+$;O2RUH|Bq#GN7WYUUe8%{2K%+sypUl+|cUg zP}SDaNGk4f<@SiJ2&D`9ooBTyC1I1%Mx%D)r8`z`YCgEhE4$SA`G6ZP$BKCeH(4BJ zhFjoN?cWVYe2lsKcIJPkRL|1;U?Nt1e^V9k>pL0QIWkBv1C zaB$s;iOQz@&yGBvOC31qxnr%&P5k_X_P28fBpr?)=2WzTmM2yDsF)qhe-OWA)gewF zHmy3;@=HMrI+cB$n6&~7O=;)-o?36VZzW(>$}=_=m`@)51a%FP?zz`WrdC2+VCdHZ z3tSmGN`bD>{oET+s=H>VYI=XSHsbcP=2hpYGPxy$!nhRfA8<=F{6s_2=$?n$2G_y- zBRZb0ISG4}#FF z>m|rM5n#I)Vr3*f3SiQ^6B8@^&~0(TprP$Ht(maST+Ak9vygKz$t-8eas3zU`Puv* z&GYkrPmD6 zHmyhNeBK=|W9QHAY-JGCLq&XkHbLf}0k&7RsfZ5Lj?dybi1kqQk*y+T9`z8ojy%V1 zJC#}_wHjZjlJ*&Lgewr^7bY$E?)3+75u%WwTY;urMW*wdi)-YGHG5^)eg%CbvhWS*>36V{3c34@sdK0up470@%JX zE~n8(v3glTYqSk2TDFSz<4QzZ6(6lIF1huBhPZjs=_=jOgTo9*;Yw2;#W)iZ2 zvK%UNGyd>dsHY1Nt3%%SH6FPBbNkx^!KjtzCCI!2VEe^wlyjFdg#W+oZwT{s-G7#^ z|E2wnQ#t);g*1q}0Ji@jE~g#apI1e@RYhCMXg9`3>)8H2lo7@^sCXwa-pz6G{zvwQ zm~Pc`7-+X1(*5VN(>R1+ESP3XxHA#)qz^r768)z=rJhPw6}s5Ed5W?6t$P4 zW{oYD8sm^KH)%Q=Z*w+c%vg000}nMwd#qV4q%hdH3p#q`YKJ1?=WFY}8pABG`RvT! zw-5VrYgQekzR|_R70ace`X$KxdKt>|PFRH0RoC3V?Zvkv)G`I#wT6*R%PD&HXf1BMGmLj`PA33`*J0NnRrnRH3rEPs; z^~Yw~{jY6&ZR5<3bXv^H`S~Ah%s;$;6m_Qp>ha1ihYz>SG>3C{%8MvzkL4eR^&D~k z1NDDs&8kBXiC!LXS@r|bt&;V9fpsty zh;B*j(&fdO7Hd;VmPzkl%{h`gQILWV3>Lk)$q8ZpzD?;Z^A7E2``(#)TOW&{U^7f`bMtP=q=uu-r!$XkxuaacC@VqoteHT| zPIE`#1Qb4ombzww%t-*-F};avvH81o=Jznc{pTa&N~PgguzOVXssxbbU2X}id1Cct zR~QAyJ(srOCaDjCG*`^N@wsZU7!BJWA@An#YpIXU!Y0fsRVtfiLVPATjDn%BRTiYx z?MTaZOhl4|0Pv1>z>ZxbXCuH<$l8|SeZM43O656){RzU{(?EPT*7ginEkaB#ptc`jdWE| z=&(^VaLPDNFw@SXkj3|8nyph=0?a8zgu(A31OE_y!D^u!xnbQ92w#5-K{ z0-!yNB+gFl1Z$Djx;Co)tJHq5X<8@-)AJzMvJeJJvd7Q9n!ki>knC}IJORusF}(@q z95eAXAX44ANCR;iz`)-s4bAzVQuvT|!iPZkKv%f6TC;DCM*ES`vfD+=Mzri`v@M$b z+Gw;c*p;$|wu?3t(MCk0-JsbyjPhsBAHrzE+C>|NXk*-H$qjN&f$ubu-DvMJ+B>Fc zdOiTD3gd_MKBDji8-Jawi_h7D0mFLF^zdCyN+UQvfyXl^m7v;_>wF0~7X6NA3d+y1 zppnG#P}>fTQDXV1UB~BQQ&F2v4;PzeW%(UHunCk>U}a@H^Ifda${ORazJm;#Ze>ky z&I5K8u^CoYj>Cf6L9EEiDscV;>o5(fDw~Jh#<6)-r8Iwkr zly5{qG?f9+)X2wB0^FXu;l0Bum zvQuV*kd6vY>gFqfH`C0>2DX@Ng~^^hn$6b$Ldscq@a2SOQda^qV}i>%J=wEQvu5Oi z_(#T{k?c9(#^1*He3Lm1q1ME1e(M;g1m1&WoIoQA0ZX%i9Y-Tt4Qw#6<7q@Yfn7@M z1a=829BE2HO15p*+3E0lyPDlIKu!^OoB=|oT}iatB-1yXv_MD{+C^fQ5(kqL&q(8~Hvvd8__Dq|psCxO)}P4>7SVx&w5VHg6O;oWka zF3u!)9|y_Fq(-Mv46zwP(*?k?i48-WHhfP*d>YH#OlLi$zX{y%y^E);;kigNHPiPc@E)3DFBsCj z&?BAE(#dN07}u8$Vp<zoTDQ68Zrj>y{C*3(07%M&leNGSOd^hZ5=J{e^lTZQ~rOfm7z*u`3r&w7d zoI73YR4Z$w^Ms2nw6aDy&jBl7ywh1a?*Nl2R9IQ#oG)E0%>M637dyksn&?>2xP0HSn4`DSLN675Rblw< zY$ZGfucD?r4{r!ugEM`vz}vG9{v5OWROc*sDpL)kJBCHWxf$4v#4r%1JC6g~3z^+v zls%m1f!)n87-b*lLtsp>I|f3(^EVg6K-k~;$;B`b4sa5{#h#=494jl!=>p$Fl(NXm z8t5G5VnG^nA+To|2BRF~m?-s+e8569%Fm!RO`>}x2jwr}i*yE7Wo6|#13Dodv1$&= zrTw893b;Frxzwoub{l5B-C@j&oc&pb@hUa}yVqD*)sAPNVSLvISiP0i;G_eSDKuDF z%bY$gcBYlJ(islyUB-)evR0eU0vB!eWNkE^kc%$yWNk5>dZ2^+U|!|Py25lW2ii<@ zwI}Na)467lVSEauy07(Q-D*0w1Kme-ohNIX>5LzumEY>gdeC%of$o6L-GA%J+F?2; zWE;kNh|v8qPu6p$GtEUW_hjudof4pX7#Yq#mt0KJRom7c6UrgIk1XPAYnJX!lp zXCqLV_p3cw2TW(Hi(cc&I%qoA1CT<2nw&^`>`ZHV3VF3?otdjq~6nX<+8hiQ4&nklb=V-Ea1 z7y90UH|1kIPAC4GRDz8?{Z0emTG(Arv@*lF0vJ>8nMJ$1$;B|>>;K;n)b?%mSq^G4Hb?LnA8Om zg=&XG4_jbQOcZLIY!|~&Q|pWa#x~b;yp>hwOmVSetgL!x2C$cz0y@72XOWAYXk|4z zX8@BjPqMNiPP2=li*9ySyBNCYCC&vdhAw)kbG3`1i(cm3?qYdX)^caNi(!hs!g<-n zFhxJhc^{b66I1k+4tFfrmGvx;t?UOEE%aoqHx2tjD7_4s^6oKvtpUvOeqbh^56>+K z@P1^Xx{ThG*5_Uja*Vzg!Jm|9KMU+1@Oo>_q<;b?B&6&HsRZJ^-y|&nu&tCYK}kw7 zj9$O-eGP9a$GPlY)0{qld(j8>Dx@_G0Jb0v82U#nK2U4tU?-s$dc<^xy)A2}7kb1V z&QADPbG^_b_HlN>$8zn39?|c-15C<9k2nzhI0UAgfk!r^_kPef8j3S?G;=-0FyN`9Qy!Vq7lj&pbec1>~IU0|05PJat>tu08;l6sRT*ghdLgNb(ewM z9eN|R-@)sE)O|=QK~ncDr#m1EuKOUS*4M>gGzo_9MewJ*g~xEv`;JH@Nbj5Nj02=e z_C?_s&Lm(zgQ+hPLAPpPf755nJV}>uOl2heWEX(X<{&*>Ec*CKQqLM z0DBEF4d8P_%mets5T^s|Geix*enYGR_|gz90Dm>aR)DVzaW%l-3~>{{-wp96fUgbl z7{CETyaMozA@%@#Ylv?E{$Yrp0lqUtCyZU+8=@z`4~7^F@S`Ed030+#4!}=_m<8}p zL!1imvmwd=4jG~r;9rJV4)BX1)&m?i#6r5(8dF>cu+|iu3a&H7Hh}e}*bZ>6 zDV_w_V2bAf&NBrE)QzTiAE3n)p8=e2ithk6nZj}m;{sE30eH?7{Q#af#Rz~GOmPyx zi>8$5e*$>j6i);E#T0J>ykUwj0p2u) ziH7)=DY^r^ZHmDFyG?OCz&oax1@JCX0C>+7^#JdiVm-hINCDtOQ``pdktzNRu*Ve7 z0DNqUw*Wpd#peK@n&Jn5&yXYZ%6mX4_M+yfCnwXPr$ZYA`RdnOY{MF*b-v^9g{PXat^iCq9YE%6?}bC&oV;CV}Y5AcE| zOmr46S|SDDC8Q4UvL%KCykdz70IynNGQciN%mjGN5~l*ZZiyOzzgS`|z#Eph7~oAy zuupr-688YSZHdPLc3a|QfOjmh8{l0_dN z1>ic57zA*=M@$5`!6W7a{LUjP0e0Ud4vG?&Lc(weD4vH0Dka@=>R`^#3=v=Jt7S7lSecF{L>>= z0{rX|n*k1a#I*qbLV5tdc*Fw$hdtscfYk}&6@WDfVmH9r1o1h*x&-kLfb|K&z-x_j z6GRt)4GBU3oR=U*0c=bVCjhi0hysA~6U3K31EjU{si!Z zEglDW(iXb_p0dRrfTwNoEx3vz2m`!i zizNUr+hQHSE4H{0;8j~(3$V);e*}2V77qZtZi}Y?{$h*W0B_jhD}Xm`@jbv>wy=7@ zylvqC?6yTOfOl*$1mIni1i*W?C;)gLMF8*tlmPh97H0x{WQ)}Rdu*{8;A2}{1@H+* zKY&kd@d&_Yws;9(uPxpK_}mtM1Ng!g{0rqiTlfI>+d=?*X^XJ{f3?MAfUj&Z7vOIw zYki;UVwktVkf|Nw)ha>ds}=1@PjRqdck&W(G%dH zEk*+TgcJb&X^Z&)Kii@L;E*jE0se*Z1o*`kmjfKO#a#faz2Yf=HD2)^z*?{P3SgaA z7`6$=4w@QQkX-+9FvfZuz?sqBs`d;zW@Ha7m&l0=P6$oCdHpQPcwbHc_kwxGYg@0=PU;Tn=zWqWA;A zm5E{-z*ULjA%LqB#R~w}B#I9Ju0`qq*Ch&cmd5poA`{?-M3DvXyF_sm!0!`9F2ElW z#Vmju6Ga)oO^G4`aC4&A2yjcHxB}qTL~$#?ZOAmh?TO-PfIlXR*8%QG6ng>gOcXx? z+?6OSKgP{O(G6f*q8JQt4-x|SQ=(V^aBre$0JtwvoC|P&qPP^`fkbgLz=Mh6et_+X z;(36FP@Vt}CyFls9!V760X&*$_5F;IT5-G4qHyj_RoI4Aw zy%L;EVEKq5u(zM&fu_#js!CH~|;Keu2+f>SEX|O>?%o7_>}xwz(Lz?Ck7x zF=*Mv`M|}H!>-QvE(Vn|oG!?POdWd=na(H|!*aEolkZ~KgXr#@>SEY~=;1WE81^7~ zI$K-}dl0>xJ6sIA4!xZhT@1SpeGK1gD29~x@mR|u8kR~>;P39756FV`V|`~hTYz!3 z=f_$m$+_GO!&)ZYxegeYe}1fGGMt-$aV_J=TBe(GH!ztUtYx}8kGS!$!0X|>;9^+d z^>KE)7`B@H&R#bjwweYy-?|vKng%&03QVSlMcrU0*~PG^%XT^g~Upb*E>liN1huSKs0%MD;1FvWK+yeV7oxQqD2RDux$gtG&Xbv6JcYB(>t z7<5i>-T=ld4}i`|&IiC)F9T4bot*tHh7wJ2esD3AXsTlm(wrz!$LZo?C{dr&-^Ea( zY0d~2!@4=$InKqfZtm>lx!4FcfLShvO~05izGQlPc%M?m z#k~;kGqSkq5w_O=`YekpF#=SE?gW~Ycn)Kd`8lAei5p$!=YggtZg$ZZfMz8A7O1ql z7lHOLddu>W73t$!nv{P)m2Ke3n&~?TZ;A&N^f2+MsRUcFqyGXRx1O?4kcRUbFbc^+ zLFPCgx)_RQva=5ui#!VjlIQ%x#ZVymjx|_^p+KfO=`M!e3A=7ChTf^b8RlXrtU_mk zi=l&^?o4$tbg(m=5*NdsXpwWei(yZ6rc>i$=;LNN%Yd=Wve3uPan=I64~-!UeO!ri zsf(eHD|N1SG4yc@o!eauecU4FeiuU@SK&PFV(8D~#S0 ztNlJE=-Z1xn{6O~a`3J+ecUyr{vhorluf8D9P7m;3dGZvY5c^qRhr z@nPx>dB!}%^B~-slk7Qo7oy;oaR!LhV7F!`dyKmkQNE2|jsR;!#<_0ztYlA;4$s)? z5@#lR(lv2l!jL?1BLWO@51yvjfu|*2#M2|*#S_b3JZ*6RPp{!WL{j!jkvNP|GVsLq z6rPqbFu_wL#!B)Dl021UF&9q{0*B5LWiqfy2A(SeZ(yLf2hRlYBA!?Y;fYlMo{6IC zaBRzpVR$Bsd^|fDDI9e>0i?ZVnowDbu1M4>II+d?&U|llDi0az-F%q-n~g zG!$vnFpZHW8x=kTYhY%r(dPBgA80i{*|El$`~bzU_*D^q_kqZtIe!MFrCT!Gq_ieV zOSck_!rOXRTDnDP!}z@qfBcsOe-z(L_Drh`;qdIxA+SXGGv_a${A1c`drVYYson&c zJjF@nkCVzn3oYg2sI(BJ`P*vikJr{OwT1H4%cz{+V%{Nq(K@07Bs%PTE%T2WBD_@Q zWw4u<13IK9OAbGCeuSy#w9QLSG%r&5$x8WTzmC=m?Ug@s{su-LYnif`CGS{Ou4il3 zWX%d)8a7kc@fJT$V!24wj&W7eibYz=!Kk!bC~Zni zF-vWyxaHa)%XNxduGO+!^CgPLk0!(4aT=QQAE312wz?I^>ozZ5xA{u9DS%(L%f_uCN>mJ7kWu zE?&u3V%DKl^h&@QIBZ*on1+#@quH}l-Dq*Wqt=ly?z$JMEE` z1i{PL#dX@#9m$~gUb-FHcKU=LDH?<4=qO)BqgF7PE2W__s%#WjvadnZ2H7UAmc8z% z13Jn`M<$N0pq5e3Q9Xe)%5zM%bR&6;W|`!3SvQciA~rJ>@!eg8>O`K`F-Pc_Q9C$8 z8+dY#4!IrgI`}i^UrX7|v9g<`>|wvttXFDQ2wN&YFkWtP$`fr%D`Z=O-rF?eqj-~{ zWZyyA=f}!EKVI+imEMIq#vK|)_1@y@y+el#!|Y4Rev-1UiIshg(z`$A1pM{XtWmvh zh}ZjfuHIub% z-UoEhd~E*nXU^|Th7HlYt(59)km?Le!dnaeW@>IEsK&PznIQH1h|#0yqR)t)FV)5V z#3CKB*dH8y7uv8CiRM(@$0(y^b< zpE-XNV{=hlWXul@9|Jg9-pUS`sbw9974oO>NKi~^N znlB5ZhVM>TKuQAQ-wo!Wr~1->r~U+g`mlbEg|u^#@-Xam8BR}NoZk-Xk9CfbLT@ri z3CmJP0HhCZmRE8(38(unEu^U2>Z>IlQ^Y!32uwLQLcZ*N~`vkOPE zQ6P3Pb2@o^$ETcN4@oWTdJ_6A&p5;5E9^>=g)TT@uu%x}vAY2%M$Edqnkgw{z(gG% zLTl~`;7%F{^u&}D^w7y|#Z!2vafYSSqtukBR76PaYI=N9E)XXwH-&P2X;O={OtY}- z5XeclCC&wv(IpL!u3eGvM1*8S)lZ@NnVAOpyJ?Lfx%+q-wMVAOfSxi@8<{~+uc!vd zS#J|*VX@aA?EF%pFSC}C!mkzjCAgY`Ph^AM$1x0llnR#q-Bl66JAe|f&dUT~k^>W> zL4!saF;$Qr0YG|xKYIGP!9R_P^0LyEd5eVKTp+@7si8Q)760T`7M(5&q!f<&o62>u# zqf43OD4bY0dP;p=Bvcn^8l4wf5~`_h2sMtLQxl9-);HERjh-1SpIux!szDQCc#898 zxWQw`j2b(3R8z&`(alYbQH{e#PdMiPJkh4*O``+qM8f~7sG1`6jlrsrG3vi7>0o(z z2!~$&S4r1|%l^BFsM26febs*#xiPe~5yz7LcaiI0L;v@Ng*rBj%G#>NQPpfn4OM}P zNbRU{G%KUJDHLohuSNjo1IiBI$Dk2t3a&Lq#!%&>um;2o8EJYmQI|f`QgG>ufYMHXWt)$A}>-7)PZ=rWw=iC| z6H5V#5M#P+cs;3WZEvR;-aDiqtJ*eCL4?4!cK1$qK|sVdy_E2ZaffYoy2CaWC~(TJ zfQ7cdQ_^U=r+2MA)H}oOjC4}gBDo^S`N&M_V*5J%0~)M_;>TJiXV|$&W%zWvXQ}Og zy%*TKYv_!!GpB>~MBBd8PCmu%hOkt~NdvT{_E(*qekYer33`CXv?@_1@9 zvTY4Rl_DVhL#yO*@s>Gn~hY@vy>>@na`7CD2erh+|vqHR~& zK9p^Dq>%yJ>@v|#83iRzuv1S3m`Hm`-eM2xlr+iCK@3!dRZ8ND&+Oz*N!LS>aij$g`t^t!YQ`%=)*B!#Hk2*$WDObBU`=BqhLAJHWx5Arj=tt^uu;K zldFVoU94GMWx1q-;2rI~4wi^&k>L=;Ji$Qi9)N5VG(&Cs_Fd>767VlA&tF!(Wq0kg z&bEr|ZYSB+G&{Kls!va_sQk8bCfYqaJ%ZS!cD8J)$=)jXyTZ)+QTlWwV_UP*?9|gx zD6$cKWL^hjU5CO$Q$R55&xzQ5iA_SaK}@CHhy4*-^T%c>xc?z-3eDnZ_9K%}TSZQ{b$_9FZH80aHfP~TLiPoY}(Lky5bXhjuQrTLQQA*A! ziipesQAINtf*oks#Z3^FpvsU<+4e4#2|fD1*Z8RadyUs2SIol<-CfL(hHk@*Xz;4V ze7`33d~R%tg#i*S5Mm*u<`Ewfs7&ON8wog>~bhQ2#5vHKu#g`uyy zQ?}krR1wD$7*Qs=Ug+HU5!<2l4>;8xiGTs$+TBKh^(4CoV@!mtueY6rw(SX^)p-V% zqJH~A*Z>B}ma2xsZRaGdMVq=4YW0KEtabKua8A6=J|3ekrOdFqGMQdrKuy?-f^S(ke%9zgQ)BmFFyxG2s8y9Jj<0frWEQ71=3K!4u)6+bW;Nh`ubE(7`)Rh zFBYp@GKTy`Me}F+vHEPn%F%!9s4=6)__Hy)tg9M%>=-QlMjd<1Pl-VKU_&_IrXU##a*GS5loT15 z00$a^jghci9ve0Fbya?<)5L{?Q6ZnuAfSAem6(UtHyTuk;l+H=7l`28|B7HE4xHCZ z4kfC&t|?qq7pjmlvD$7_@v4JO)kXmx^Mf_bp{dBS!5Q+=M;UPuYJ-t-#W#gV+BYgr zBwk+Muw2HU0*{O?*EEup%hipfRhQ$Ql9{2}`o`sQvELTU<2?w~<&heLrBRSK*J!|v zA%Ujq+E8r(+YpUdKLo1l>lYjCNpg{8EDKj01;$8olTlETJK3m;fB+&gUyiEDi`34- zlBF0NA)_2*IFuB#ddxWTKr)}Cxdl~T9c(lrxO@YvFswTQSOis2PzgztgtVA~#8Dft z&B6*pD^VJ*&@6Slqa{X6Bp9wSV2y#uvN&lWBit0Is;Mu7x@GnCHHJ(dG!z9(9HRBo zjM3%?%bS~P^FlSj#&8;XiN)5VwBVRlor)j%?*{$!KEj~9fc!Ov71mk zkF2OB?BFz2hOzK=!;4*ttnC7<7E7AZZjGo<#)|~lVj_VitRam;EKKLrqx?gSGBDf_ zD63hF;+)KSD6EjgvT&d}ENcl@mP9KC%hSdPR(x0-W7!l9E zBEhnn&}`D-BC5ehwSlJsTy1cf;^gMaN(3#d4cFljT!tEMFqW0G9X6NIPe4>P5@7Xc z&FBS|qJknptbp^Hxnf2MGhn%a1`p+fW_gA~<#_t_YRkMp$Keb-1R&ppl`um*HxhD%E!C8`+znq0L7LtnFea;=0;mCEnC&iD!)*$M)}ei%z+@15RTLV%?0=(Jd1DCe zxVX6tfq2Ge4cv91rO?9Nr%-$#LtA4iHWdTd50HBk5~H526!5TnH)i1>b3jabD%eM{ zhvnuTcM2HNgzG&d;u7mCqrRneFeLB=Yx#7wpgzLUl^J#b6@24jU~T%pzz`suh8V z{f_d*QUOS-4_CO}26XR?1Zrb56;pn_?c$4~llIiZyzdSzq%iclT9R3Na+TIsFeW|1NLlRRu8aVx1NBz-D3+)8SS)+;f& zu@qOgtyKDC;lU#-8W1&xG~r?2jlrfW6d}gW3IOA>1Qp@hCVJ!s5q8q(N6gxK8C8w? zAi4Xu@WObjl!$srsi|QM6ehOr=nFShG}bpXpd2J3TY>b}RjWP#JaK!&RBH95RaaS5|BZ38fBIGVTB|sALn2Aix3v7=xT$R!IFYF zc+UWnn^Id*!nQnRW?o?4tQoUrpFB(Yi}Q=}r<5r299$WdFTI7ciu30xY91IgbzVtf zQDMm`l4I8Fl7hln(~L8lQ5CXZWbUP}Bv@sX1Pbd^A<~Ebj5!1~e_2B#>OkJ*RuY)g zSbs)HO(sEzd$lBoVD3>2qgFFIjwPXabsP>#0+Z#oYOZ8e{@GNcxLgV^4xQ=xg0*Os z8j+cc_0O)WS*~#e%QyQJm8Ecb9reHi!kxs5} zT&xO0;pp*0XooIeGa6{EMyA7*k(*f<2aD?K8{Fd1?9}mnuJs4oZ_H7(qLMhk^hw+nUWNw9UEbDd`Q@q8+trFeixHoq)6Q zz%nz~xL9M-bU0_yxLfbaAY3e_l3kLjTNjI|ZkH5a=Por`@$rP&jV{h2jQW)wMA4`* zxRhvp#}Qn!aEWbfBcALUh)dO0;-VPjqo(50V(rDHwHl2}(U#+)apvO^V{FJJO^F(k zOQEf}e%GX2T$Xz*gKJz-25n(3PBU};($-uAM&^2>R_79w>A9G)KNn+yu3uWBi@4?( z#c7i+l3NoF(opB}3c~qV52@}7Kp}GMph;@Og?8xHL6ACQGAb7YZUfOsZewF``CQ3H z3j06An1$(7MQ&r2MrSu@Paftmcn2ME*)Wh6R%!%BSQBiN@}m5cv37EUo6CyAb!n1v#vY$U_N2?gskrc^Jf&#SKu%APQuAlnKeahX`}PAi~lb0gOk zv)xL-P!s|ITGYtysYK48^0~!;$kK93%4$@7vk7SZrZ(2sYVYhilv^b}4REtxSQn|E zQWI=$VhxbVwZ~~8Osd1uWL(n8)yNXc2nHF;sVp&;5^IvNbk&SpOLWD$MjFf6mZzQh zxshEPba8EIF52D(-H;eVj3?0=T}q4*x}-Li=#tx;V>CotVJuElbn&PGx&&>7F=&h_ zy3{H4t@h~BT8+}BXv=g_*F0T3-UwZ)vQgRJG{RV;JrtWYY(me6G&W6bqsZ1fyCI?j z_&~U+t*&%<7+?rUhT!OrG0u#(U=-e zG@{0Ajl>Munxe*hH&_oG8dXDpM$`zPk^D28!J$sasHwU4ur|_ZMRa19KuaY0XkZUE(MzC#~~U)Q>Af$5G~i*4mm3 z>r+;ap6|qO9HQIhz9Kp$7=xZPyFC^9jSx4!(1&wh7O)suz?O)t%BY_f2T~D6763%j zKI|1~-)}hWM3}OtisDGE;>1T#usn%i?=6H$r$Xj6R3PsfQ3HuaWLsDBQN`Ly!1@D8 zNL*QWG(IMZC`dWiRgtD)&(Td-`sbq4i%mgy&vP2XOR#-{4Fw%IrKY|qGzXK3U`>?L zjEw>Gs4^GawspN~S4Ghw54SAqkUT6@wYQ`ZBX(<6xu1oxKnG3@VV79@)s#;sA|y^cLM#I>i3VCAO0v+5&Q#b|_e#U4v$WL{lOEE=;Xq#5RiLrdL=^+C5v zr%2V}ieHf`$}}@GA4Sx*s}8}?P=l^WV=9`g>D*}Pt0KkpSScy<%vF;@(T>7$$%ZZ0 zHk9gmS6R$|%7cyZ`j+6+m$+o-6k&oEM`>#yF*tJ+gK`4sMwQEdcCSrnUz#{K6y|Ex zW#KAcZrr*Al}D`pYlE7kOd9)TWf)~Tq(y~GR;f&sqzY0EU3}pamk#Dhu3n07c7yEA z;+SSPObynCvF3~^^)|FQYExZvC(tCi=4u*KCF!o;VkKH6|(wpGLC zCZLwYvTa9{nVen5b$xNWa+=M3!gx*D_M-_=B6(a3m>WXpjRkEijYBbZ!6P9~Q?)Er zJo(rRi6hAQSZs1J98%Ac;yiTvDEA;1-Z2GOQj9983|BSBbxbOisTHoZN)fH74%SO> z`2}gLOm|%s8=#`_)6|*4h6Z%ru@TynSv>8jDkrjSv2rlzBSUVhYz>@=J$j5LI)&m; zc@gLO8jaIk)u}3uLKJpm#MM2vLRFOfW$2b-ELW!Y>qI$}vDK**v>fhI#WZy#rwtMF z>c&u0HFhXsI=H#qRxJ+}a%UBrv9Tpsyd0foyh+Td2Xh=#97QQ3JJd?-p1Z>2yd2}# zl=_`0v?0toErS+>sXzuJ05C%24$cnBSxPYF_AzV%GF`iKvm$8_P;|-Kr>Pdn-2)PWZ zuH_~MNKAukQ+QQYl_)vB=@pO6shpL93Bj5yg=6W{b}1B-UQAL^%})+Ts;97*RaOg; z%!^#TM0wn`40>sVt1LzXDW5{Hn3m-$KMCf{fLV~;mhLq5{7NcO6kgm~c&>)BJ~7MT zjEchqT4OX7EC{$i6~!^DFP58Rd=pKbkPCMShq+y-F^aV=_o5`uBkJp_EMwYq$~CkeAS6v zgHQpc6MSDSCuwYjm{{iV9T4WtZX0YR%?(AG8|zRVdK#;$MD_VPR!L!=T2C-bn61=> zrr?#DeBB8O`pmiY_)fl#g;&y4>musKa+4t^rkK4~VPR6uH_;?a387i>YgSC`vFC_! zTl?@DNBiXKX3VCrGhBf;%!O!^jP354^Tj--$oQTZuU6b#(oZ6?2LnUo zk*Z3Cahn4~H-ShM-c<3OZXGsDBUR;cK7q}88B<}HOvGTEYk;vL1OsWLl0d?B;fNwY zWhO{FCdB&-Ko=;g+-%1n7uA;@yf5TTJx~@xj};0u)-RR$amm3-XxNU*KRlpl+R?R; zChoLzvfF{EHevYK8NBUM*W@;-YihgH#$a6(ujUFy*>YHeu_V}tMh95Kj~4=j z;3S_)6te*NKDiZRYv=o9MUhX{0N{;!Xv^}eqHt5QdS8H0yc=x{*J9d*h72UM41c`g zG(w_SXH|q@RVs`juwgc7vZDE;O~H%FNcm#<@q(nIv#-$7YOvv{m@)I!?_9ydcf4qV zM=im4h|h^2tkysVgLuKo!hkS z8myH)N3a&V3dlzlzaIh8+`!2ce0ZOLYQa#`>MdK2mogINrvpo|3R0LZG8t0KIRW02 zB1F|(u!ebpWcf#oAorT1SREGrGF9XiZ`~MwKI|4BFRWRfdjJ@wibiA3GO8LnZzcWH%u$HJqWgY5D>4DLR^?}dn*puTyCn?Z~qYHovgGX&ek%Y|CG9@jD zMg$K&erZJVb%9#uSQ0RYkZrkAE(Ddo9QomJg#g#==7y^9!nHh9(TvUhR=QLbC>n?| zDuw|GVQ%6UFKvZnHq-hBNu`%25=Eq`ON{k~#;N7BmH`A*RxHKKL^<-uOac%P;in!f zh=wZmqEG+@I7hzz38;x9sQ3u25TiPB!GG>G@yi~y`x&zXQdl8*+^@BaNIkcMYC@rg zLXOpq%?&8WRw8FWhWv9&1Wf{;#38FoFi%1|l|k~uqZoY7v?+nYSta>%XXO^bilzkS z%q}jOnOh8sM2icj70jEXyz>H+bEnM6pOq)kSby=n;`|axg=a4PMJIF4iFcYIcmw&R zQ;Oyl7tYToQe2QbH$RWQlXDA8@b(_B;R93W=I6@~2m@0KkpMp>4CGTU<(->9b2ehP zk^{5m6%`q!xl=Hsn-9i7aY^pnl32o&*)wMr#!=?v&dn_<$}bAE56Yc9J3e-lw|&Um zd<5plCN*bneg`t6B90J@NC;^wOX=o@@p-2F`jq~-FEb6YVFxkX`ps=6x(t4#tGdflsQ&6(SQpcG$aRMshs(5ZMCU+$3@b$`a#V6| z8G4F#Op+SqK|#=u-YVKFDKzG@L=f;9ZDHNa`BSFEa^+T>f!U8{gqc>L?3&n{NgoE} z0A`PTMJfN17bU81YXcZ6@I|kVCYj-vR$Pez0zK?90|d>?Z#HXaGy(cJ+HeNMudeCF z@^O?=ZD8Jt4@4WwjZze~Tpb!1r_k}^i$iSHVGW`-j={(ecEfe<2Yn6bS@CUX1k)|0 zEE*yhlEnIEiHstnE(zexX-t$RqV<@F zAYK5i7oT^-7xNo41?Mc}#}MEpjX#%uN)F0-l$wnMR6g+T22+n3Kc-Ut`bs~xa5&ZW zFRc!jSNk#j@t1}CDgwSc&(=B&jr~?T`k6Llvk^0ia-)CtvXLjEHTe5a@@Hqq7-M0@ zQ2&^rLyf8O8&T{8VUfoPa{p|Xc?rhLVMEE&KReQ-1jN#qV0)^pRYpO&(XX(H_iqhx z<8`1;|Lp8xfdB^5`o`>`L;aH``Ns`4X z=!eUJ!yizO=n(Y3{uLDG7BCH*s%sn%$G@iXr_#mWjq$@@SNY#o{?%88^E3w@>cRs@ zcxDHW+rS;RhjGxf%mZZ+$1$`r9|Hgf!QrqydAI5aK%A6fjD_QA9^>K2e+=LRxNV<* zly>27K5Tw%{S_;R?0xXcTe6N$D|-K@(t|7Rd2ZPSXC0h8=!1Sw58qaGW~A>b`-Pb= zC**e8Ui!(k@BjX{zx&(5cgh!Rem3KQEhmkfAG#~?lHZO9ZGZUgi!OP-$8*2?^9?t? z;hb^nP_ego&i3#(-+f&V${n4544twB&5l?@7>{DXcd%hlfKbd*w#*`sP_bdM8VD9xC4 zr{7%o_tj%}Ex!Aoi?ScM_Rbxbto$bR)KlNN_{Qg++i@>di+X{Ch++ zaq{uU6Xl4H94b+R=T{Mbm4<^Kk9r|~9}NgU9-K&gBhMPak5}3f|4L$p!6O=ppQyum z-zM=jS|6U)NW55w^N1_reQ2ck@ys#eS3@p;JlKsmPf+BKx7-ph|X@%g$u zc?cKrhXDEG$y&s}*Z6}vf8E$2;5QI9%J5-ci5k3Fm-rxU4?NO|_#?XfcpMb*EgI)_ z!Ngbdfgg{8r1w5uemqZ%_&GX#9^6KJFw)_VM{W^csq@40B8k7M6 zHC-M&4ve^8$LDE~#K-FV@$56=#en?r23g{xb$LAqKZ`yU#4y|qaBsu;bpCl>BT(Zb zEpLd%|4t%)y!V*i2Q<#}Bk4Uy^FN{Uqt!Eb<`u*Ls>_e3;t_ubeEhj%f)>|qOkiLA zKjAqJGI2PD94{yz#fkL1fHuaK6q02B&-56U1V^e5E)9<9b=Ht$4v(JVn8We1?O4+v zv@E!RaD(93M36lxgL0T&q7$Gj;P_QRV;Q-d}i9=t6%GX@x5DD{^r;R&b)2evL1i__N6|l<6m8| z>7kaD7wwPu5A7Uw`WttSYCKT+U{-m-=JWl%zq;u7`^TisE-hIyI`gi7y?J0k`kfON z^uP4Hd*|=z;lK57FApm`DKPi;ul7a!ulJa=;D%dX{OR(;#S8xa@h#!^#nwM%E;74* z@ksZa6N8scd-Ln77FK-v%$NRc3C=L2bwSP0f z$E@C%vSj7JkvIIg>hlG~x20YB?XKQGeO-I<7X!zy-S-r3Bl`1#F}_c4dwlW-pC^2r zzA>f8j0-0|^2v(}bI;$na@pvNN!?CA?b2%>=sx7d1A&uQ_q*}F6TklX;Roj4miE$> z&rW-#sUY<9!E;ys{=2Nz-j^pwb_6e2xo6SGS6iRnclkG;`v3Sn`1-ay{6=_RQtJqPz5-1l(2^{+SFD7aj>61Xb36>yv3Zh*TN?pe5Z;J$)84A&(Y zZ3pfoxVdm4xMgsg;I4yv5bi~|58=LnOX!4oAlxuGUa&R??hLq9a9iO10QV@|+i+jP z{R^%;8u(baJh+qL&Vb_`Vq4&DhkF$6ZMZMt5>mkrHw2Z^dbqW4*TCHk$Kx4!A~E|N9#PDG1wY<mDn!!VP)U<`L^DY*4MxrY@#A4|B=L+m&Bg2M*!}Zb zJCJy>9Z&AUuLzOI%!`9HGp{ZuiAR2G(i9z^m)n7q4xr=nf@?DK9A%vso{CQruWQxu zc|kBqyfavH@nC0?c)q&k;th7xvR0+S%k2=4KOW9bW}dsPnRzxINj$+%>%uz;N#Z4i znu`~QP$VxD0f|?NXl8l+Izo6YyJqHn&5X~hs5R+ZkQkpgH-f}Fl68D}fH^{VD6?kf zHOpjfQOvx6Su^vh2!`+q2{7{#2_3?_?U^R8yw_rQ2P;Xu{#TQ5=!lG8sYty2RmW$m zBr|US*37)}ktE&%skwM7BGczxz~JJ2i8_QAeUkZE#Md>$QwmAqsfuoVL?($xQR-B9 zXFN%~L|&74$0JF+2vU=HSp!MD!$FgHXgNtdh*6Vx>mb$Rb%Y@C5O$p~uaPIS><|I* z<86^7@d8QBB@b^0iKoSDk@9M3ka*>^Ch=ZpM&xOnn)DM;l6dB#&OLABAZeIC%EfES zNg9D(P^ZXyQc2nSe9go;^NiUI)0-rNgndA)#K5W6v;Dpb^O%`B8hjC z=!m?elO*2SskzS9`QoXln#AkMnJ}+02Z>i?==i+ygz+)+8RoPtx92E?zT0Qjb>BT&*#0r`HjAk1;iVOQpygjn*GuEoQuhX0TIgI7RaN>;V5IIatweLc^5bsa;{&7Yyr?AJk_3J=0j<% z*+`v!UTgYm`>Xi8kq2D7lSjvYO1GW2Rome`oe2G-%! zT9VksXs&Ej3%PjVt|sL|21&dEL6dl260^j6ltAK5N?PP*aFY3|R{eP+6q$Kb6qtEe zlxF^ePJd}@`VS9M%)D0x%)D7eGuMHMl6g0~COrX^q-;F2W~XY>8GxF^OJA8juY?7O zS10QDyxy4cc{Ph>{sbtQtMCAcEk`r+wqr8$>SIkh8lfbyed_q>nv~Z{;;F3U;$f|t ziwcv()5SIEK~4Iil_am$02gog&|I(Tx+rL^iz_vWm)&SCUJn9259sixj}X3tHHu%M0-9SP ze5Rvn`Fl-)cHswf_|PMS`(elY{ZoN<@%?E3{GFsgyYNLi{E8!l^TbR3j+Fl#9nQ9i zUpx5?=q&iV?Fiw1v;+RQuYg~>_&GY9d)Xa@FVf+s93gy%4oBPKubq7NwEnS22zL+Q zf9nY0IVmb&-x0#y)Accb<*!}(?h*Re93k92Cx6lr!rjC1ogU;=gm2UFk2ym40UiF$5%fQx4X5%5;fr)nyz&U)?xE*L z(%(JkTvv0u{JCeHb59DtcHvq*!(1`fFqfs9>8XiH?2|ZVaQ|#$DSPU}huJ^NU#>5G zgEhtR=C6}2pL}_6V@^?gx}U~ar1?}VDX#|p37Sv$*B$b01z(Ql)BSdbe2>J))BSgc ze4l~OujTz3ANN<2{sTU)@DAv5`89b9!MFQA;9C#A9sdE}9pJlF^XdMs!~DJxBkyVC zUH&?#k3-2Ua0ib<41>l72sQRy5e)& zTSx8V0`Qe;K0TgvD36QKIhs$8D;@H^55A3>PmeDh@^RIG7sR zz7om{sQl`2r$fG#;459E`1JVGA>WPQo1^*kIMgBEOW=D>^Xc)ZLq5K<+@tyQxY8kC zAIv?T3o8Be_|hR?9{AGB72mJPs{!9Z&G&2awt_Dwq~z&-zr%F7UtFO1ru<5KG7;XzH#7NRHgLO<64J&3&D45wc^v`TZeq>IY&F=-{GRF?+x%B2rGGd+-t`d#tS0I=*yeN2`6Yc6tE}ucQOHU0l&cj1Q{b=07P3Gc?%$> zY?+q>V)2x@NyC+Z10m;3zyW|&fb+3=vIr0>)yxtdev*QlCje%Fudjw(02wbuLw-0x zJwC?#0Da%cw*e`K7r7HYui^cGc=t5&9>D&Hf1`$%04@Z*7Lams0GZF;8t%dUE?8BM zd>as}zP>8}8D0r^I_RYuF9KwG#{*(NW#kA=?+%FJV{>Of%HM^Ktq5=jAmv=9VFe)N z&DZ#JK+2l{NO{9F-2%jXW90W(QZoLF8g2&!f8Q(qUti|}BUN?A@mr+>4YFWbBtfn$ zmWKsq0aHb5AxnK=ps)xSX=pPeyS$3>+TB27O@~tD6|i8jF@z3gXNEcReFv(&PeQe~70T{h zsQfdb?CSgq*}cQ*BcR4_ko7m1eazQ*|HfLIKMKdgjc_veZ7rMxS6aW^@)CG2`T9ZC z`>$)mcU|)D!Cs`l302>#Q0@7%dDz@x{Z`BR_(J)fFc(`t$8y1(VUC0vhk;Pz&=qPN zKBaQC=Ny#1ze0_}F{ke}ABSq+ccJpNnhVYQq3nMh^4=yM0cC#xl>OdN<*tUZf1XAt z{XHnVZ$jx$nlGDMpz`S>2AZ6o4>6I~CsHbRKUBHN=6G|6^|9sa%%0{4d~T!i??9E; zr{^mS0r(K5^5 zf*R-EmUEUnFrxZjgR*nXJYw#K_2{35s&^gaC;lG)DF4F{Q~83^KO`~F&pF6X{1*QV zM}FP%33xs75y*Rye7n=NQK0m_P~~?yU3-GVkbi1~DU->;W}@bC8#Y_`hAl zhj8&HkR>=i17$~hyK2W@pzQzF>AyDjn%m5+kfk?%3bG`|Yn=WFlpXDXXj~c~k3#+y zsChHY`hjL_c7b{xKIS!8?R^_6|4Ar&FPncfpNGo76KcFRK+U%jRJ|=w<+S&$`8Lhz zd02=14)1N0uN`Wh?|~}c=5)Q6Qu*&gm2Y*dKD`>5IOHGv*W-D3?27 z9yDJxH=1kAvF5GjMJ9{N|I<8f9x|bEglZpf8E???ld1WA2l0Ie|IhSCCdZMi+T6o{GEBgTy2)jZ<^E1L1t{8 z9G=)aZmu&|nj=hqmo4}9uq6K}bDO!vY&I8|x0|EPGeeW|r_HVAX0yQ@Z|YENjo)?V zN4&U5K4b1Te_?Ji*O~;E5BclNcX=pPzQg>3dB|LCmdvl1H=F&Ht!E7|YYBnV6M6M31-oa)+ zcn$Ie5|#cB^KVe;?UubkmfPd>HBMh)E_3=+%M;ALPCw7{&7Zk*CjaLN_D5UhaY))_ z-e9hwe=4W-qn0I?$1=JbGOW=ANLs`iQp0O^bPwzW+2X9}1}8$GJ(C*kPsmQaS!-$$ zRJvYA#CEgIESW{K-mEnvvxCJjlsDVVl36tC%~~@uJA6Od%{H@S7R`FI){M*!Di8IW zZDz?Vn)PO_8JQi76MyE~%{H@S7R`FI)&!y4Rg6Oo297I%i}yHD4HI(8o*+j1(Mhk& zx*nn5($BDd0rRNl4~t%e@yZ~%lb~O0O%eyZ9>o^+q(upz$Dcev$R%Y7`T`%3yogz~prKgM#=@=w&h9(-=^{{G4LBi)zS<^1VB)CRXV-Ivhw zF8k>|$AfNvy6>{X`O|%pgX$0Y(|wmEX@7O&xw^|9{r$xK?c(u__9pt%Y9IP;mOrxG z%d$>}?}?3c-;ejmL2lOr&UFBL(x>}QT8AX3`=H(EujG2_(6!0-^xW#&&Tr7y1Ti{c zd+9#dw^P~u`IXDpGtRm=zA2PX_icAtuXRS3K2wwZDg5es#qAksc?)UMr&lX~OKxXe zbv4*tx^JuZt0BMZpX~bg*~S9vwXW%U$o3Xne~rM$mEX-lL-HkczK7APf_8n&L^7`@XwULpQ|4YKvFztuwrMZd!Ze*qBiCKxN$T7n`R(2;2Yp=evDL{x zP_Ob;%`M}ah_I5}7rG=D;ey>8lY5YH^)3*dfxsP0 z7jwvI%hE;;@*r-*!bOQoZn$aw^D=FyD<729xrLqludkGe@sRiTmDE)Z*jLOFe8H=< z%#ey#c3toXCeT^q><|>@!H4d|i#8n46s9V7x5{0a@y{d>S{*Os#EU*0w88*aQWP^I zNlj;M;*uRkEO>TT`EiFtCR*A3yOJw)882rkJA_yARFZ->bEK(s+4GgS(Yl8?k2lU+ z!2Jvd&?a|XC!bc_$mt5Po^V!{%k!P7b9tfc_g{HT6#X_z+MUE?i3)QFbhEH!PGUC= zBA_TF;mE2mww1dO6_Tk){1QSR&Q8T~jYO}-_5c6On~cuWC6ih;OG3qA{pjTAUw%xc z*mb|0Q02~_jCI!cJdE?yO6Uxp!KKZLIhMxKAjn4=izCF=Q201S2E)O95i_wR4G|i3 zdN#unG%cJx)4BT&sZeQP66>HMpi5C?I(> zE;)s$!1Lm0;+DO8IFg`~>i)FhyEYz%)gI6^Kq~hEAlxKz}R<-cDyG%|Mb#XC}}h zk%X4oVVK<@ECQlNWf6HqtEf*KAD{(n_)`jtQUoQkRc=_=4YkrJh3xyD`<NFOY8*QPH38$Z0G7s zG09uMD^9mbHwp)_ugHzIN`BKM&CbtkNwjt((n#~>w@>nWTlk5gmXaG&zgVh0Q);j` zzu}MCqAMi_Vpn@hIjfjy#xmJ-vVD!Dd-ID_*@Pw1NR4$iuDT-8G&|d`PPWI*WP5W; zVRwJrI^ULTk_?Ewc?d}brkQ9lo72&@gq`ZGpC$Q8_Zq~sxrrR@Za3Oun)P+d>Kt6! z-pVD-gK2Nfm$pY|n(eJ-W_{c0RIAyMO;4Dg&W`r$tQYO$IF*zAFwHfoQm>A!U%Aw0 zp~w(>^JCkzGtJiM`_(TZ`E3;eVrPDAZ%}83&@|)GY_yaxMt=)zT1c}1JM+`YIyBAI znbIg5+uo4m_qY~7=*$mY=yGg(1l}~4G+cN=xV}NpDIsB#_8NlYbL@1s)0x*vhS9B9 z!B-AiIl^8CLth>A0)ySY$S?+xPTQsJ4TcS49`KS&fR8YY!;#hmPxpp+*3l21lbJYy z>sVqFxxrlCN(grfk_Qa zYG6_WlNy-Rz@!EyH881xNexVD;O|!h%OklzERAe7TCvAp-P`&*|5aBDX!AMX?DjCULzOO!a`EY%1`5V?Q9J!!^ z-@w~6O5%AzBwrrMRosReM{?668y<^%?(#H&za*RHdZYq%uU39`Pcj^cF3J;H`pX#E1 za?2r9@pI9UYLrlAw@#8h(uEv8U&rV1*iAlUW^lws|_CxIbyI#qatot+iw*~tmU;&%h&syccg z#Hq)yDw&pVgdx;ThYp9W*U*wk-aiP_R?1TY21B~uGhSQ+&1qO_;8{w4stLtWXU{LR zPd(o9HS19fsz)70a{I0OFw3~r7)0;)pKq&i37Ly(WX)Ye%)0C-<{|_AobYg9lggJB zK&zE{(6VW|We#(9%xAiO2h+X<+uwh@m7nt(MU|EgOwOG=-urOq`3p)QYN)ckvc+{QE$n#%%`o2Q|vI#ocuDj^3>l)yX-HT&!m9#lca3MS_K&oHk6 z|3(BHJc#xn3WcJ)it7gxu}9 z5$lG(npqBnSXB`GvkCn~;5tSXS9d(p4@FdUM4|SRXeZ{Koz_oOUj7qQO(CUgbOY1J zte3^H+c}b-rlwT)en8XJTCsd2U&dwTv@&qo<6qNZzgTmvf$$!?%3&+;(Da_a5Ck^z zl>Tj2i$f0cx< zO2{<&C*ZfhkF)HA?Mx~IY#^icm)4u`xy>f)_MGjid5 zrJ7nV;F}QCIg(R*rk;g%LCRhVwSQ)Z6>0+P@j}J#fVNFTw$@z`l2rhk-T`b4RK?VW z0l6{s8`iOsHRdtwCj2j8e&dL-1=UX3HGjdLcZT=-ZVd0|7G!wSA)CYd13wM#zx+|x zdS^Y1uW7J|;mA4Rk-&xwO4bWfrf>cu3P0+VnWo2kv|2I@C z{8cXA!_bOc_>GdvhOU9MDnf>|ydQ8pa;+O!EOQ63|M#4A@}c7+xrItbrjptxn4VjF zd}%+g*GuRAS?^YUuFS7ylL{)9BiPo=jyM{+(5=6kITo$ryYG3Mcp{|wTWqViz{PtC za&c_{`oX35*vG2|VBEihT|4xSO^|0RW!RM)Vs{rRwj$VeB`bFo1f+6$E2%7lmS*K6 zu!-O~Xno{szef9${o%9kdfT-a1@>QUw<|-=q7FWT3b@;)X1+or zEUb1RS!pO3=Rw^x;O=#P%$q4~R^46uOS^$(s);qDw7^2eFA;3JmMy&rMy6U?Y;O0u zsU@+ww%Fsg*jFglMX}{Yu?AOh8)f*trvz$xZ8?*2*HLbkma`tf$WxP{y;ZQRG}J@& z!sMXYMzoH5h_HoSs%m@Q-vmo9DSMp#=y>)QwreuYuF0>Uu5CB5Cbyt`X|sPn&7i3J zc?Z1x^bJV${{y7Z<4?JGzk^)d{RA#;f47sB>&_S0*75AGo4r@4Nvfb?AuD$?EB7|% zWMrheS-# zS7xtq_M0eoAnyGZ-d{tTv1W9QVBukTfrmQxThCxo$6~`5x?_@Rw{Mp)nC%fv!jaG_>9d%IBaj|jHi4~wuGQN|ECp`IVoii;NXuOnV-y984G zKY$c?Z*cKORZVx77Ako)DPVt?uWbOYwGb@OPw6#hBd@!_3J2AEagP51=qa!XZ@b0% z%!VAhYiD@WH}sCGV|cI!vm0FChJu50KV((M=5eCHHyY^BitKpJ7wH-8+vGC>UxLN6 zFeDE8Pz_8{{zo8GYVN-M-sWC`j_rTUZtiU^-ZZMGfU*MIj#JOC(U}klJQN;9*H3u< zf&M?x({+HE1U80QX&3^L^%N?UoUs7?&sVcZ?Age?UC;p3?%z(MD0cYXx4jx@K^6P+ zwgzr>@phnAuJ>BxmL>mVz_3s_+EF9NXUf~RL8EjyrRz`KDkVrQzL;?uuzpf@IzQWIVjnSSR-M8ItL_YC&VADU7IS*3K z|Fk02K7oKPa0B*Unzj{*Ls{ZN%}K0J-v28VU|;FaQ!w9%>??X1o%d{WB+$M+P&s2Q z8r2+Fy`wo$S<$KDmp#%PxOV&AK=~}p8DuPyG>DPCVZ|0=g0 zpqc2y^Zbk-bACF<7x)q_56!xpI6ocQvioUzB-c1HgbfT*v2)AM*gyv7v_3j#H#%u_ z&TrK7W%c}>dJd}RtLnK&J^!elG?mdgudC-9>iO^LIjo+0)pMVEzO9}k>iJjoq|uJf zc~3ogm@+!2Og*RKxuh^_1_*UaN9Vi?J@>Yt*2d5u(cl(t?}lDx>>S3PW9(AK9%qaO zHuMl@jOp}CLio^O+z2Jb5eDHy@W^vQAJ4W`T@{UWcD9-EL~C@t(U@#cwnbZm(KU%+ zsyUcW#8T;aCU|vAGS(7|Mcad`6G2-b5f4^oKyHs`<{9gf@iQ{nXtpzBtjQt{Y#?u= zV~xooV#e&sbszmCQiHQ=gO!!b($V%zG?q=K+8g5Yg4Ofp8Rtint%-PDCX+}r83LO5 zs#G$5>OAtyuFPia44i2!aBOOGs7tD~*Nvr7~$H%@hCS5}^i%hBm{ zDqT5mUa+<{c;-A~X=@_U5uDT7N!2jugaU$`V!d zm+&MBPnYm42}2ToTEb-#eqO>B3DXi@E8!*ydnLS6!n-B>zJyyPd_=;hCH%F7gA#gM z+%(sn(&xdNIygbPrcZ{G8kp3;qy{E6FsXq_4NPiaQUjA3nAE_e1|~Hyse%7b8aQ%x zWYux!bxiLlzerW+}}xjQ&EpQVZHvUDP$^V;n! z^5R4+(Js}l$3I4|Y)iHq-J9`2p;#*?iz1_hWsL@&9qCjIg_@a`XgU!GOthw=aTEW0 zn~tWFi46XCo;*^s>5#~@v?bc`%LLJMwzI=*Nu{nddXEg5{BeOej(|FhZp%?S{2Omv z{fvRR8vluppB?DtDWh_}UNMrj5%frXqB+@~Sk#%xrrH|Xvnx<~baiXO=rz_hfgD~J zOLXw8E84mUr)Wua>;>9N(4gc+o#`}`;L<%sSJ`BCbRs@p&w{4~JYoy6wVlbdDzl@Q zcyXdN5zVN?bx2e;@|o6nB9pZ>X{_z`>GY-T(T+?@D$8zQ@tbYR%4EEuy>Z2&MVd}p zFKHJi)+F%{&*_yo-&+)IZCxFWL7m3h+il|7P83rYk85Mikk;p=EoF}^?TE%yCGRC! zB{j4svyo_~g+g0gsY|oz&RCY|TbUk>qmPo;DDmw~Xn~ZONkr2zCHy$kGG;5ZNSR$e z)!*v8k9fC@@!Jitj`e1&MKKLBvAF|3=a6kClSRBHkKIf7MsSxrZr|;bWJj5Hg~qij3%6!!fu*VJUKOuGnSq#=kAoIlNt_Gk(*V zarYF|5Sf(0Vxz72Xv{uLMqAlAxHIMt8{aRhGX~1eV||TR%bKLd@02Y{wY8zK-=3oL zeXtC*z5)3SvSwRw7FcGtc6Zt8R61)s2vTN#{ z%asf5@-+?ms=LcVeZJ6^vMp1B!By3v-m+m|5D5s&=&PGT-BX9lx~Ei^qXgu_Gkop% z`NoNPjM+TJXS{XRIV;G+!(x7*;5jp01N_MjO!~?2yWr`FFT}%%DZgC~oR@-5d5y_W z`D%DNV#+(QDqrMRfv(CIe6aGoQ%#qFr@Y2mK1d=QG0P7Uz!9_jkjQrdQ(j}zS^si) zI%3K@G39xemF^~Z%4I6&KaI6~2>H?xQ~x0XIAZF5P~>MKPI-+a=?7DOHU2S%?#m*tv6io91dajAcVd>m3jdZw$D8>qUt>g7`CAx)V?cQ)rhGXk zTDYGeuJk9E{H%Wvo{pIEK>|2p%2x~jPQ)p%G3f^*-z4(<4JFEJtmRiBA39=|zls2k znB{K~`PUJryvC%ne5bup-iawcDDv+jPI-+HRq`Q(bi|Yo5x@~sK6rwH#!+RqyvC%n z{BlO%7*O7cDPPSm`EYYYUSsl8ewai!E$_st{GcKmXX^3=^FNU`+9dVV`3bq0pA$2` zkR&|Cz{F3)b=-jKDEq`A*F8`#z$`2CrMOe2vL}Fy(I{6WpsJud$YQmN#Dc zLHS;bJ)GTs!CKyFzm#`k)?a@Yeoy2z*78ku^@{CxV%2^rZzev}tM+@!4|(LBnDY92 zb5P_p*5w-;{S^${TXm;YyL$Sj(4#g^rl=PE7f7k>4ot8f$r8@}bl68s7~5xl{2^ zSiF-6_kF=<3VvGfLczSPME-LH2M{L?39b@cFZd#2+`BavsO*iE#7BT%aEsuG;2yzE zf^&jf1baFgH_g7x~76s*^iFACP{!_688?F!u{I3&1F%M0!otjF_{ zg8O8AzO4BL@6}kw&$MZFd-ZrYQn0q~Qv_>!4GGrv*GLSVYWw1?T4HTqn+0q8x<|0K zucriS`{Hdz%4_?Yf$Nhq9rkq$vBSPj7Od^7Rqc8um491*8Aa8 zH2oyoUOp~ZuaBS6c&<&qO!LeBvO}4$1pSpWvY2`vmLv?H>!)?;G0% z>;3<~Xnxrr?-AT5`3(y$7y7$`R|);7Lv4NN_rWT``u&Xmi9mff3IFASy9H-}K`!1V zyvc*V<-tGm;1@mE@?c(7cjiAGm)xEBBoF?C2Y=dwFZbZ9J@{4+{*ea{c<^sM_&+?@ zkFn;g?*~2j3=gjJ;EO$Yg^iJ=?f9=o07ZO-2e0$UU+xoGusPKkE)L(Fhrg!l@E1S5%yU|I zqMXCJ6WwRBZkj%yb*CcZ;@PjNp)L#u&FZ8!EQRy@S(mA4b@s8VlJgX;S=4c^K7v(@ z#d>HK7u8iC%@J;o7nzXeI5}21;y$r`uHW2l6cgH_*%*G)SW{E7rz1@w}cfpzEvOC-#t_m-$u-s{Ta*TM-rQXsrGej zGs}D6rj}If1g^db-GVvHn8wjf2a!rN2EaCT%z2usqlD z@poan7-Xd}qlS=Ly*xABMDwAnW5`5F$>i>WP4YdmIJbJ|+KJ|5J-gbgse2`}(`1F! z#T82`&UosBu-aDGn+5j}1c!9@tq6$pX)^23-5GZWvHu_QpeuRa3wmfWO(jkl%QO~ z;6)tVp0RIJIIhvCXz@lx>5fM6Qic0Ah3n3S<4y$@(*ME@AAQSX+?7|ZWsJGf!xxhO E1n-SLHvj+t From 3190eba2e4f5cd3afe3f07fa67cd6ef527c20fdd Mon Sep 17 00:00:00 2001 From: Stas Kelvich Date: Fri, 6 Nov 2015 14:14:01 +0300 Subject: [PATCH 03/46] automate tests --- .gitignore | 6 ++++++ tests/deploy/cluster.yml | 38 ++++++++++++++++++++++++++++++++++++++ tests/deploy/hosts | 11 ++++++++--- tests/deploy/hosts.sample | 8 ++++++++ tests/perf.yml | 36 ++++++++++++++++++++++++++++++++++++ 5 files changed, 96 insertions(+), 3 deletions(-) create mode 100644 .gitignore create mode 100644 tests/deploy/cluster.yml create mode 100644 tests/deploy/hosts.sample create mode 100644 tests/perf.yml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c321a93 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +**/*.o +**/*.so +tests/perf/pref +tests/perf/pref.linux + + diff --git a/tests/deploy/cluster.yml b/tests/deploy/cluster.yml new file mode 100644 index 0000000..ec1fc6d --- /dev/null +++ b/tests/deploy/cluster.yml @@ -0,0 +1,38 @@ +--- + +- hosts: nodes + + roles: + + - role: postgres + pg_port: 15432 + pg_repo: https://github.com/kelvich/postgresql.git + pg_version_tag: xtm_patched + pg_destroy_and_init: true + pg_datadir: ./postgrespro-data + + tasks: + + - name: clone dtm sources + git: repo=https://github.com/kelvich/pg_tsdtm.git + dest=./pg_tsdtm + accept_hostkey=yes + update=yes + force=yes + register: dtm_sources + + - name: build dtm + shell: "PG_CONFIG={{pg_dst}}/bin/pg_config make clean && PG_CONFIG={{pg_dst}}/bin/pg_config make -j {{makejobs}} install" + args: + chdir: ./pg_tsdtm + when: dtm_sources.changed + + - name: enable dtm extension on datanodes + lineinfile: + dest: "{{pg_datadir}}/postgresql.conf" + regexp: "^shared_preload_libraries " + line: "shared_preload_libraries = 'pg_dtm'" + state: present + + - name: restart postgrespro + command: "{{pg_dst}}/bin/pg_ctl restart -w -D ./postgrespro-data -l ./postgrespro-data/pg.log" diff --git a/tests/deploy/hosts b/tests/deploy/hosts index 8ae34b7..899ec64 100644 --- a/tests/deploy/hosts +++ b/tests/deploy/hosts @@ -1,8 +1,13 @@ [clients] -localhost +158.250.29.4 ansible_ssh_user=cluster offset=6001 +158.250.29.7 ansible_ssh_user=cluster ansible_ssh_port=2299 offset=3001 [nodes] -localhost +158.250.29.5 ansible_ssh_user=cluster offset=5001 +158.250.29.6 ansible_ssh_user=cluster offset=4001 +158.250.29.8 ansible_ssh_user=cluster offset=2001 +158.250.29.9 ansible_ssh_user=cluster offset=1001 +158.250.29.10 ansible_ssh_user=cluster offset=1 [master] -localhost +158.250.29.10 ansible_ssh_user=cluster offset=1 diff --git a/tests/deploy/hosts.sample b/tests/deploy/hosts.sample new file mode 100644 index 0000000..61a49c3 --- /dev/null +++ b/tests/deploy/hosts.sample @@ -0,0 +1,8 @@ +[clients] +client1 ansible_ssh_user=cluster offset=6001 + +[nodes] +nodes1 ansible_ssh_user=cluster offset=2001 + +[master] +master1 ansible_ssh_user=cluster offset=1 diff --git a/tests/perf.yml b/tests/perf.yml new file mode 100644 index 0000000..fd70263 --- /dev/null +++ b/tests/perf.yml @@ -0,0 +1,36 @@ +--- + +- hosts: clients + gather_facts: no + tasks: + + - name: generate connstrings + set_fact: + connstr: "-C 'host={{item}} user=cluster port=15432 dbname=postgres' " + with_items: + groups['nodes'] | reverse | batch(nnodes | d(2) | int) | first + register: connstrs + + - name: make a list + set_fact: + connections: "{{ connstrs.results | map(attribute='ansible_facts.connstr') | join }}" + + - name: copy transfers binary + copy: src=perf/perf.linux dest=~/perf mode=a+x + +- hosts: clients[0] + gather_facts: no + tasks: + - name: fill the databases + shell: "./perf {{connections}} -g -i" + register: transfers_result + - debug: "var=transfers_result" + +- hosts: clients[0] + gather_facts: no + tasks: + - name: run transfers + shell: "./perf {{connections}} {{runkeys | d('-g -w 64 -r 1 -n 1000 -a 10000')}}" + register: transfers_result + - debug: var=transfers_result + From 7bb81cff952ece29b2390a2da7489c83587879c7 Mon Sep 17 00:00:00 2001 From: Stas Kelvich Date: Fri, 6 Nov 2015 14:29:13 +0300 Subject: [PATCH 04/46] transfers.go bugs --- tests/perf/transfers.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tests/perf/transfers.go b/tests/perf/transfers.go index 91c6886..b5e6544 100644 --- a/tests/perf/transfers.go +++ b/tests/perf/transfers.go @@ -39,7 +39,6 @@ func (t TransfersTS) prepare_one(connstr string, wg *sync.WaitGroup) { exec(conn, "insert into t (select generate_series(0,$1-1), $2)", cfg.AccountsNum, 0) - exec(conn, "commit") wg.Done() } @@ -134,9 +133,6 @@ func (t TransfersTS) reader(wg *sync.WaitGroup, cFetches chan int, inconsistency snapshot = _execQuery(conn, "select dtm_access($1)", snapshot) } } - - exec(conn, "begin transaction isolation level " + cfg.Isolation) - sum += _execQuery(conn, "select sum(v) from t") } for _, conn := range conns { From f25f685abadd22a3a4ca046b6d2d59e5b91d3500 Mon Sep 17 00:00:00 2001 From: Stas Kelvich Date: Fri, 6 Nov 2015 14:53:45 +0300 Subject: [PATCH 05/46] fix local deploy --- tests/deploy/tsdm.yml | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/tests/deploy/tsdm.yml b/tests/deploy/tsdm.yml index e997e04..71f8ccb 100644 --- a/tests/deploy/tsdm.yml +++ b/tests/deploy/tsdm.yml @@ -5,19 +5,26 @@ roles: - role: postgres - pg_port: 15432 + pg_port: 5432 pg_repo: https://github.com/kelvich/postgresql.git pg_version_tag: xtm_patched pg_destroy_and_init: true pg_datadir: ./postgrespro-data - role: postgres - pg_port: 15433 + pg_port: 5433 pg_repo: https://github.com/kelvich/postgresql.git pg_version_tag: xtm_patched pg_destroy_and_init: true pg_datadir: ./postgrespro-data2 + - role: postgres + pg_port: 5433 + pg_repo: https://github.com/kelvich/postgresql.git + pg_version_tag: xtm_patched + pg_destroy_and_init: true + pg_datadir: ./postgrespro-data3 + tasks: - name: clone dtm sources @@ -35,7 +42,21 @@ - name: enable dtm extension on datanodes lineinfile: - dest: "{{pg_datadir}}/postgresql.conf" + dest: "postgrespro-data/postgresql.conf" + regexp: "^shared_preload_libraries " + line: "shared_preload_libraries = 'pg_dtm'" + state: present + + - name: enable dtm extension on datanodes + lineinfile: + dest: "postgrespro-data2/postgresql.conf" + regexp: "^shared_preload_libraries " + line: "shared_preload_libraries = 'pg_dtm'" + state: present + + - name: enable dtm extension on datanodes + lineinfile: + dest: "postgrespro-data3/postgresql.conf" regexp: "^shared_preload_libraries " line: "shared_preload_libraries = 'pg_dtm'" state: present @@ -44,4 +65,8 @@ command: "{{pg_dst}}/bin/pg_ctl restart -w -D ./postgrespro-data -l ./postgrespro-data/pg.log" - name: restart postgrespro2 - command: "{{pg_dst}}/bin/pg_ctl restart -w -D ./postgrespro-data -l ./postgrespro-data/pg.log" + command: "{{pg_dst}}/bin/pg_ctl restart -w -D ./postgrespro-data2 -l ./postgrespro-data/pg.log" + + - name: restart postgrespro3 + command: "{{pg_dst}}/bin/pg_ctl restart -w -D ./postgrespro-data3 -l ./postgrespro-data/pg.log" + From 1cfcad8f178fea50f0da4e420e97aeb24bf46e8f Mon Sep 17 00:00:00 2001 From: Stas Kelvich Date: Fri, 6 Nov 2015 14:57:43 +0300 Subject: [PATCH 06/46] fix roles --- tests/deploy/roles/postgres/vars/main.yml | 4 ++-- tests/deploy/tsdm.yml | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/deploy/roles/postgres/vars/main.yml b/tests/deploy/roles/postgres/vars/main.yml index e3059ee..22631bc 100644 --- a/tests/deploy/roles/postgres/vars/main.yml +++ b/tests/deploy/roles/postgres/vars/main.yml @@ -27,9 +27,9 @@ pg_config: - line: "port = {{pg_port}}" pg_config_role: - line: "#pg_config_role" -pg_src: ./postgrespro +pg_src: ~/postgrespro pg_dst: /tmp/postgrespro-build -pg_datadir: ./postgrespro-data +pg_datadir: ~/postgrespro-data libuv: version: v1.7.5 diff --git a/tests/deploy/tsdm.yml b/tests/deploy/tsdm.yml index 71f8ccb..5885191 100644 --- a/tests/deploy/tsdm.yml +++ b/tests/deploy/tsdm.yml @@ -9,21 +9,21 @@ pg_repo: https://github.com/kelvich/postgresql.git pg_version_tag: xtm_patched pg_destroy_and_init: true - pg_datadir: ./postgrespro-data + pg_datadir: ~/postgrespro-data - role: postgres pg_port: 5433 pg_repo: https://github.com/kelvich/postgresql.git pg_version_tag: xtm_patched pg_destroy_and_init: true - pg_datadir: ./postgrespro-data2 + pg_datadir: ~/postgrespro-data2 - role: postgres - pg_port: 5433 + pg_port: 5434 pg_repo: https://github.com/kelvich/postgresql.git pg_version_tag: xtm_patched pg_destroy_and_init: true - pg_datadir: ./postgrespro-data3 + pg_datadir: ~/postgrespro-data3 tasks: From a222a72d7ef1df30a964d2a291d256da0f8bbb9f Mon Sep 17 00:00:00 2001 From: Konstantin Knizhnik Date: Fri, 6 Nov 2015 15:14:30 +0300 Subject: [PATCH 07/46] local deploy fixes --- tests/deploy/roles/postgres/vars/main.yml | 2 +- tests/deploy/tsdm.yml | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/deploy/roles/postgres/vars/main.yml b/tests/deploy/roles/postgres/vars/main.yml index 22631bc..7f2cb83 100644 --- a/tests/deploy/roles/postgres/vars/main.yml +++ b/tests/deploy/roles/postgres/vars/main.yml @@ -22,7 +22,7 @@ pg_config: - line: "fsync = off" - line: "autovacuum = off" - line: "listen_addresses = '*'" - - line: "max_connections = 2048" + - line: "max_connections = 512" - line: "max_prepared_transactions = 400" - line: "port = {{pg_port}}" pg_config_role: diff --git a/tests/deploy/tsdm.yml b/tests/deploy/tsdm.yml index 5885191..f42dd51 100644 --- a/tests/deploy/tsdm.yml +++ b/tests/deploy/tsdm.yml @@ -29,7 +29,7 @@ - name: clone dtm sources git: repo=https://github.com/kelvich/pg_tsdtm.git - dest=./pg_tsdtm + dest=./pg_tsdtm_test accept_hostkey=yes update=yes register: dtm_sources @@ -37,36 +37,36 @@ - name: build dtm shell: "PG_CONFIG={{pg_dst}}/bin/pg_config make -j {{makejobs}} install" args: - chdir: ./pg_tsdtm + chdir: ./pg_tsdtm_test when: dtm_sources.changed - name: enable dtm extension on datanodes lineinfile: - dest: "postgrespro-data/postgresql.conf" + dest: "~/postgrespro-data/postgresql.conf" regexp: "^shared_preload_libraries " line: "shared_preload_libraries = 'pg_dtm'" state: present - name: enable dtm extension on datanodes lineinfile: - dest: "postgrespro-data2/postgresql.conf" + dest: "~/postgrespro-data2/postgresql.conf" regexp: "^shared_preload_libraries " line: "shared_preload_libraries = 'pg_dtm'" state: present - name: enable dtm extension on datanodes lineinfile: - dest: "postgrespro-data3/postgresql.conf" + dest: "~/postgrespro-data3/postgresql.conf" regexp: "^shared_preload_libraries " line: "shared_preload_libraries = 'pg_dtm'" state: present - name: restart postgrespro1 - command: "{{pg_dst}}/bin/pg_ctl restart -w -D ./postgrespro-data -l ./postgrespro-data/pg.log" + command: "{{pg_dst}}/bin/pg_ctl restart -w -D ~/postgrespro-data -l ~/postgrespro-data/pg.log" - name: restart postgrespro2 - command: "{{pg_dst}}/bin/pg_ctl restart -w -D ./postgrespro-data2 -l ./postgrespro-data/pg.log" + command: "{{pg_dst}}/bin/pg_ctl restart -w -D ~/postgrespro-data2 -l ~/postgrespro-data/pg.log" - name: restart postgrespro3 - command: "{{pg_dst}}/bin/pg_ctl restart -w -D ./postgrespro-data3 -l ./postgrespro-data/pg.log" + command: "{{pg_dst}}/bin/pg_ctl restart -w -D ~/postgrespro-data3 -l ~/postgrespro-data/pg.log" From 412ccb4813b1b929615582d570d8ae14577344b9 Mon Sep 17 00:00:00 2001 From: Konstantin Knizhnik Date: Fri, 6 Nov 2015 15:15:19 +0300 Subject: [PATCH 08/46] gi --- .gitignore | 2 -- 1 file changed, 2 deletions(-) diff --git a/.gitignore b/.gitignore index c321a93..e185144 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,3 @@ -**/*.o -**/*.so tests/perf/pref tests/perf/pref.linux From b976bef03e5d5b89a0f0c479ca0003f06c9d9c9a Mon Sep 17 00:00:00 2001 From: Stas Kelvich Date: Fri, 6 Nov 2015 15:19:43 +0300 Subject: [PATCH 09/46] perf --- tests/run_perf.sh | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/tests/run_perf.sh b/tests/run_perf.sh index dd16f43..46dd259 100644 --- a/tests/run_perf.sh +++ b/tests/run_perf.sh @@ -1,4 +1,11 @@ -go run *.go \ +go run perf/*.go \ -C "dbname=postgres port=5432 sslmode=disable" \ -C "dbname=postgres port=5433 sslmode=disable" \ --g -w 8 -r 1 -n 1000 -a 1000 -i +-C "dbname=postgres port=5434 sslmode=disable" \ +-g -w 8 -r 1 -n 1000 -a 10000 -i + +go run perf/*.go \ +-C "dbname=postgres port=5432 sslmode=disable" \ +-C "dbname=postgres port=5433 sslmode=disable" \ +-C "dbname=postgres port=5434 sslmode=disable" \ +-g -w 8 -r 1 -n 1000 -a 10000 From c1e62b0f7932d63852060f079878f5f73c0ce3b3 Mon Sep 17 00:00:00 2001 From: Stas Kelvich Date: Fri, 6 Nov 2015 15:25:14 +0300 Subject: [PATCH 10/46] clean before make --- tests/deploy/tsdm.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/deploy/tsdm.yml b/tests/deploy/tsdm.yml index 5885191..120c57a 100644 --- a/tests/deploy/tsdm.yml +++ b/tests/deploy/tsdm.yml @@ -35,7 +35,7 @@ register: dtm_sources - name: build dtm - shell: "PG_CONFIG={{pg_dst}}/bin/pg_config make -j {{makejobs}} install" + shell: "PG_CONFIG={{pg_dst}}/bin/pg_config make clean && PG_CONFIG={{pg_dst}}/bin/pg_config make -j {{makejobs}} install" args: chdir: ./pg_tsdtm when: dtm_sources.changed From b293a3efe11b078a23fe8c0a65b4e85b45ab14a0 Mon Sep 17 00:00:00 2001 From: Stas Kelvich Date: Fri, 6 Nov 2015 15:28:38 +0300 Subject: [PATCH 11/46] one relative path --- tests/deploy/tsdm.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/deploy/tsdm.yml b/tests/deploy/tsdm.yml index 00893a6..31e47b4 100644 --- a/tests/deploy/tsdm.yml +++ b/tests/deploy/tsdm.yml @@ -29,7 +29,7 @@ - name: clone dtm sources git: repo=https://github.com/kelvich/pg_tsdtm.git - dest=./pg_tsdtm_test + dest=~/pg_tsdtm_test accept_hostkey=yes update=yes register: dtm_sources @@ -37,7 +37,7 @@ - name: build dtm shell: "PG_CONFIG={{pg_dst}}/bin/pg_config make clean && PG_CONFIG={{pg_dst}}/bin/pg_config make -j {{makejobs}} install" args: - chdir: ./pg_tsdtm_test + chdir: ~/pg_tsdtm_test when: dtm_sources.changed - name: enable dtm extension on datanodes From 7a47f56ecc6649d8910b2e25dbadbd33427efaa7 Mon Sep 17 00:00:00 2001 From: Stas Kelvich Date: Fri, 6 Nov 2015 15:40:17 +0300 Subject: [PATCH 12/46] abs path in perf.yml --- tests/perf.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/perf.yml b/tests/perf.yml index fd70263..83a0068 100644 --- a/tests/perf.yml +++ b/tests/perf.yml @@ -16,13 +16,13 @@ connections: "{{ connstrs.results | map(attribute='ansible_facts.connstr') | join }}" - name: copy transfers binary - copy: src=perf/perf.linux dest=~/perf mode=a+x + copy: src=perf/perf.linux dest=~/perf mode=0755 - hosts: clients[0] gather_facts: no tasks: - name: fill the databases - shell: "./perf {{connections}} -g -i" + shell: "~/perf {{connections}} -g -i" register: transfers_result - debug: "var=transfers_result" @@ -30,7 +30,7 @@ gather_facts: no tasks: - name: run transfers - shell: "./perf {{connections}} {{runkeys | d('-g -w 64 -r 1 -n 1000 -a 10000')}}" + shell: "~/perf {{connections}} {{runkeys | d('-g -w 64 -r 1 -n 1000 -a 10000')}}" register: transfers_result - debug: var=transfers_result From f9a1b2a658ea211d10584dc85894133f17612686 Mon Sep 17 00:00:00 2001 From: Konstantin Knizhnik Date: Fri, 6 Nov 2015 17:55:24 +0300 Subject: [PATCH 13/46] Correctly handle case of equal connections --- tests/deploy/cluster.yml | 2 ++ tests/deploy/roles/postgres/vars/main.yml | 4 ++-- tests/deploy/tsdm.yml | 19 +------------------ tests/perf/transfers.go | 11 ++++++----- tests/run_perf.sh | 6 ++---- 5 files changed, 13 insertions(+), 29 deletions(-) mode change 100644 => 100755 tests/run_perf.sh diff --git a/tests/deploy/cluster.yml b/tests/deploy/cluster.yml index ec1fc6d..79e7e2b 100644 --- a/tests/deploy/cluster.yml +++ b/tests/deploy/cluster.yml @@ -10,6 +10,8 @@ pg_version_tag: xtm_patched pg_destroy_and_init: true pg_datadir: ./postgrespro-data + pg_config_role: + - line: "dtm.vacuum_delay=10" tasks: diff --git a/tests/deploy/roles/postgres/vars/main.yml b/tests/deploy/roles/postgres/vars/main.yml index 7f2cb83..2a73cea 100644 --- a/tests/deploy/roles/postgres/vars/main.yml +++ b/tests/deploy/roles/postgres/vars/main.yml @@ -22,8 +22,8 @@ pg_config: - line: "fsync = off" - line: "autovacuum = off" - line: "listen_addresses = '*'" - - line: "max_connections = 512" - - line: "max_prepared_transactions = 400" + - line: "max_connections = 2048" + - line: "max_prepared_transactions = 4000" - line: "port = {{pg_port}}" pg_config_role: - line: "#pg_config_role" diff --git a/tests/deploy/tsdm.yml b/tests/deploy/tsdm.yml index 31e47b4..8bfadc8 100644 --- a/tests/deploy/tsdm.yml +++ b/tests/deploy/tsdm.yml @@ -18,13 +18,6 @@ pg_destroy_and_init: true pg_datadir: ~/postgrespro-data2 - - role: postgres - pg_port: 5434 - pg_repo: https://github.com/kelvich/postgresql.git - pg_version_tag: xtm_patched - pg_destroy_and_init: true - pg_datadir: ~/postgrespro-data3 - tasks: - name: clone dtm sources @@ -54,19 +47,9 @@ line: "shared_preload_libraries = 'pg_dtm'" state: present - - name: enable dtm extension on datanodes - lineinfile: - dest: "~/postgrespro-data3/postgresql.conf" - regexp: "^shared_preload_libraries " - line: "shared_preload_libraries = 'pg_dtm'" - state: present - - name: restart postgrespro1 command: "{{pg_dst}}/bin/pg_ctl restart -w -D ~/postgrespro-data -l ~/postgrespro-data/pg.log" - name: restart postgrespro2 - command: "{{pg_dst}}/bin/pg_ctl restart -w -D ~/postgrespro-data2 -l ~/postgrespro-data/pg.log" - - - name: restart postgrespro3 - command: "{{pg_dst}}/bin/pg_ctl restart -w -D ~/postgrespro-data3 -l ~/postgrespro-data/pg.log" + command: "{{pg_dst}}/bin/pg_ctl restart -w -D ~/postgrespro-data2 -l ~/postgrespro-data2/pg.log" diff --git a/tests/perf/transfers.go b/tests/perf/transfers.go index b5e6544..90d762c 100644 --- a/tests/perf/transfers.go +++ b/tests/perf/transfers.go @@ -67,13 +67,14 @@ func (t TransfersTS) writer(id int, cCommits chan int, cAborts chan int, wg *syn gtid := strconv.Itoa(id) + "." + strconv.Itoa(i) amount := 2*rand.Intn(2) - 1 - from_acc := cfg.Writers.StartId + 2*id + 1 - to_acc := cfg.Writers.StartId + 2*id + 2 - + from_acc := rand.Intn(cfg.AccountsNum)//cfg.Writers.StartId + 2*id + 1 + to_acc := rand.Intn(cfg.AccountsNum)//cfg.Writers.StartId + 2*id + 2 + conn1 := conns[rand.Intn(len(conns))] conn2 := conns[rand.Intn(len(conns))] - if conn1 == conn2 { - continue + for conn1 == conn2 { + conn1 = conns[rand.Intn(len(conns))] + conn2 = conns[rand.Intn(len(conns))] } exec(conn1, "begin transaction") diff --git a/tests/run_perf.sh b/tests/run_perf.sh old mode 100644 new mode 100755 index 46dd259..cec51c4 --- a/tests/run_perf.sh +++ b/tests/run_perf.sh @@ -1,11 +1,9 @@ go run perf/*.go \ -C "dbname=postgres port=5432 sslmode=disable" \ -C "dbname=postgres port=5433 sslmode=disable" \ --C "dbname=postgres port=5434 sslmode=disable" \ --g -w 8 -r 1 -n 1000 -a 10000 -i +-g -w 64 -r 1 -n 10000 -a 10000 -i go run perf/*.go \ -C "dbname=postgres port=5432 sslmode=disable" \ -C "dbname=postgres port=5433 sslmode=disable" \ --C "dbname=postgres port=5434 sslmode=disable" \ --g -w 8 -r 1 -n 1000 -a 10000 +-g -w 64 -r 1 -n 10000 -a 10000 From d21ad6636c639fbae131f49737d811e8b8cf4e87 Mon Sep 17 00:00:00 2001 From: Konstantin Knizhnik Date: Fri, 6 Nov 2015 18:41:26 +0300 Subject: [PATCH 14/46] Change DtmAdjustOldestXid --- pg_dtm.c | 4 ++++ tests/deploy/cluster.yml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/pg_dtm.c b/pg_dtm.c index b60012c..90528ce 100644 --- a/pg_dtm.c +++ b/pg_dtm.c @@ -393,6 +393,10 @@ static TransactionId DtmAdjustOldestXid(TransactionId xid) DtmTransStatus *ts, *prev = NULL; timestamp_t cutoff_time = dtm_get_current_time() - DtmVacuumDelay*USEC; SpinLockAcquire(&local->lock); + ts = (DtmTransStatus*)hash_search(xid2status, &xid, HASH_FIND, NULL); + if (ts != NULL) { + cutoff_time = ts->cid - DtmVacuumDelay*USEC; + } for (ts = local->trans_list_head; ts != NULL && ts->cid < cutoff_time; prev = ts, ts = ts->next) { if (prev != NULL) { hash_search(xid2status, &prev->xid, HASH_REMOVE, NULL); diff --git a/tests/deploy/cluster.yml b/tests/deploy/cluster.yml index 79e7e2b..84520da 100644 --- a/tests/deploy/cluster.yml +++ b/tests/deploy/cluster.yml @@ -11,7 +11,7 @@ pg_destroy_and_init: true pg_datadir: ./postgrespro-data pg_config_role: - - line: "dtm.vacuum_delay=10" + - line: "dtm.vacuum_delay=60" tasks: From c752b7994b9ccb53de07e5ac144f7de09e8af3f7 Mon Sep 17 00:00:00 2001 From: Stas Kelvich Date: Fri, 6 Nov 2015 18:57:54 +0300 Subject: [PATCH 15/46] fixes --- tests/deploy/hosts | 3 +++ tests/deploy/roles/postgres/tasks/main.yml | 2 +- tests/perf.yml | 4 ++-- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/deploy/hosts b/tests/deploy/hosts index 899ec64..c9d4501 100644 --- a/tests/deploy/hosts +++ b/tests/deploy/hosts @@ -11,3 +11,6 @@ [master] 158.250.29.10 ansible_ssh_user=cluster offset=1 + +[local] +localhost diff --git a/tests/deploy/roles/postgres/tasks/main.yml b/tests/deploy/roles/postgres/tasks/main.yml index 517dbd9..6df0e0d 100644 --- a/tests/deploy/roles/postgres/tasks/main.yml +++ b/tests/deploy/roles/postgres/tasks/main.yml @@ -48,7 +48,7 @@ when: pg_pidfile.stat.exists - name: force rebuild on changed sources - command: "rm {{pg_dst}}/bin/postgres" + command: "rm -f {{pg_dst}}/bin/postgres" when: pg_sources.changed - name: build and install diff --git a/tests/perf.yml b/tests/perf.yml index 83a0068..69d02a5 100644 --- a/tests/perf.yml +++ b/tests/perf.yml @@ -1,6 +1,6 @@ --- -- hosts: clients +- hosts: clients[0] gather_facts: no tasks: @@ -30,7 +30,7 @@ gather_facts: no tasks: - name: run transfers - shell: "~/perf {{connections}} {{runkeys | d('-g -w 64 -r 1 -n 1000 -a 10000')}}" + shell: "~/perf {{connections}} {{runkeys | d('-g -w 8 -r 1 -n 1000 -a 10000')}}" register: transfers_result - debug: var=transfers_result From cabe53cef392eaccaf33012d432c568dab8738a8 Mon Sep 17 00:00:00 2001 From: Stas Kelvich Date: Fri, 6 Nov 2015 19:06:36 +0300 Subject: [PATCH 16/46] point ansible deploy to new repo --- tests/deploy/tsdm.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/deploy/tsdm.yml b/tests/deploy/tsdm.yml index 8bfadc8..9515868 100644 --- a/tests/deploy/tsdm.yml +++ b/tests/deploy/tsdm.yml @@ -21,7 +21,7 @@ tasks: - name: clone dtm sources - git: repo=https://github.com/kelvich/pg_tsdtm.git + git: repo=https://github.com/postgrespro/pg_tsdtm.git dest=~/pg_tsdtm_test accept_hostkey=yes update=yes From efeef65fcf2faa2aa42a43b1da5b8748e672da54 Mon Sep 17 00:00:00 2001 From: Konstantin Knizhnik Date: Fri, 6 Nov 2015 19:11:03 +0300 Subject: [PATCH 17/46] Separately report sleep time --- pg_dtm.c | 46 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 32 insertions(+), 14 deletions(-) diff --git a/pg_dtm.c b/pg_dtm.c index 90528ce..fc276ad 100644 --- a/pg_dtm.c +++ b/pg_dtm.c @@ -115,9 +115,6 @@ static void dtm_sleep(timestamp_t interval) { struct timespec ts; struct timespec rem; -#if TRACE_SLEEP_TIME - timestamp_t now = dtm_get_current_time(); -#endif ts.tv_sec = 0; ts.tv_nsec = interval*1000; @@ -126,17 +123,6 @@ static void dtm_sleep(timestamp_t interval) Assert(errno == EINTR); ts = rem; } -#if TRACE_SLEEP_TIME - totalSleepTime += dtm_get_current_time() - now; - if (now > prevReportTime + USEC*10) { - prevReportTime = now; - if (firstReportTime == 0) { - firstReportTime = now; - } else { - fprintf(stderr, "Sleep %lu of %lu usec (%f%%)\n", totalSleepTime, now - firstReportTime, totalSleepTime*100.0/(now - firstReportTime)); - } - } -#endif } static cid_t dtm_get_cid() @@ -155,7 +141,23 @@ static cid_t dtm_sync(cid_t global_cid) cid_t local_cid; while ((local_cid = dtm_get_cid()) < global_cid) { SpinLockRelease(&local->lock); +#if TRACE_SLEEP_TIME + { + timestamp_t now = dtm_get_current_time(); +#endif dtm_sleep(global_cid - local_cid); +#if TRACE_SLEEP_TIME + totalSleepTime += dtm_get_current_time() - now; + if (now > prevReportTime + USEC*10) { + prevReportTime = now; + if (firstReportTime == 0) { + firstReportTime = now; + } else { + fprintf(stderr, "Sleep %lu of %lu usec (%f%%)\n", totalSleepTime, now - firstReportTime, totalSleepTime*100.0/(now - firstReportTime)); + } + } + } +#endif SpinLockAcquire(&local->lock); } return global_cid; @@ -449,7 +451,23 @@ bool DtmXidInMVCCSnapshot(TransactionId xid, Snapshot snapshot) { DTM_TRACE((stderr, "%d: wait for in-doubt transaction %u in snapshot %lu\n", getpid(), xid, dtm_tx.snapshot)); SpinLockRelease(&local->lock); +#if TRACE_SLEEP_TIME + { + timestamp_t now = dtm_get_current_time(); +#endif dtm_sleep(delay); +#if TRACE_SLEEP_TIME + totalSleepTime += dtm_get_current_time() - now; + if (now > prevReportTime + USEC*10) { + prevReportTime = now; + if (firstReportTime == 0) { + firstReportTime = now; + } else { + fprintf(stderr, "Sleep %lu of %lu usec (%f%%)\n", totalSleepTime, now - firstReportTime, totalSleepTime*100.0/(now - firstReportTime)); + } + } + } +#endif if (delay*2 <= MAX_WAIT_TIMEOUT) { delay *= 2; } From a7f967403d04f09003f07ae60d5133692035a946 Mon Sep 17 00:00:00 2001 From: Konstantin Knizhnik Date: Fri, 6 Nov 2015 19:22:36 +0300 Subject: [PATCH 18/46] Separately report sleep time --- pg_dtm.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/pg_dtm.c b/pg_dtm.c index fc276ad..9c559e3 100644 --- a/pg_dtm.c +++ b/pg_dtm.c @@ -74,9 +74,6 @@ static HTAB* xid2status; static HTAB* gtid2xid; static DtmNodeState* local; static DtmTransState dtm_tx; -static timestamp_t firstReportTime; -static timestamp_t prevReportTime; -static timestamp_t totalSleepTime; static uint64 totalSleepInterrupts; static int DtmVacuumDelay; @@ -144,6 +141,9 @@ static cid_t dtm_sync(cid_t global_cid) #if TRACE_SLEEP_TIME { timestamp_t now = dtm_get_current_time(); + static timestamp_t firstReportTime; + static timestamp_t prevReportTime; + static timestamp_t totalSleepTime; #endif dtm_sleep(global_cid - local_cid); #if TRACE_SLEEP_TIME @@ -153,7 +153,7 @@ static cid_t dtm_sync(cid_t global_cid) if (firstReportTime == 0) { firstReportTime = now; } else { - fprintf(stderr, "Sleep %lu of %lu usec (%f%%)\n", totalSleepTime, now - firstReportTime, totalSleepTime*100.0/(now - firstReportTime)); + fprintf(stderr, "Sync sleep %lu of %lu usec (%f%%)\n", totalSleepTime, now - firstReportTime, totalSleepTime*100.0/(now - firstReportTime)); } } } @@ -405,8 +405,9 @@ static TransactionId DtmAdjustOldestXid(TransactionId xid) } } if (prev != NULL) { + *(int*)0 = 0; local->trans_list_head = prev; - xid = prev->xid; + xid = prev->xid; } else { xid = FirstNormalTransactionId; } @@ -454,6 +455,9 @@ bool DtmXidInMVCCSnapshot(TransactionId xid, Snapshot snapshot) #if TRACE_SLEEP_TIME { timestamp_t now = dtm_get_current_time(); + static timestamp_t firstReportTime; + static timestamp_t prevReportTime; + static timestamp_t totalSleepTime; #endif dtm_sleep(delay); #if TRACE_SLEEP_TIME @@ -463,7 +467,7 @@ bool DtmXidInMVCCSnapshot(TransactionId xid, Snapshot snapshot) if (firstReportTime == 0) { firstReportTime = now; } else { - fprintf(stderr, "Sleep %lu of %lu usec (%f%%)\n", totalSleepTime, now - firstReportTime, totalSleepTime*100.0/(now - firstReportTime)); + fprintf(stderr, "Snapshot sleep %lu of %lu usec (%f%%)\n", totalSleepTime, now - firstReportTime, totalSleepTime*100.0/(now - firstReportTime)); } } } From 062a09ced7038899e3edee2d9908c5ecee1920d3 Mon Sep 17 00:00:00 2001 From: Stas Kelvich Date: Fri, 6 Nov 2015 19:31:09 +0300 Subject: [PATCH 19/46] point to new repo#2 --- tests/deploy/cluster.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/deploy/cluster.yml b/tests/deploy/cluster.yml index 84520da..6398609 100644 --- a/tests/deploy/cluster.yml +++ b/tests/deploy/cluster.yml @@ -16,7 +16,7 @@ tasks: - name: clone dtm sources - git: repo=https://github.com/kelvich/pg_tsdtm.git + git: repo=https://github.com/postgrespro/pg_tsdtm.git dest=./pg_tsdtm accept_hostkey=yes update=yes From dc88d68e3c2aa700bd626e9d2d585ed1a84e26c2 Mon Sep 17 00:00:00 2001 From: Stas Kelvich Date: Fri, 6 Nov 2015 20:02:15 +0300 Subject: [PATCH 20/46] copy go sources to the server instead of pre-built binary --- tests/perf.yml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/perf.yml b/tests/perf.yml index 69d02a5..35f1402 100644 --- a/tests/perf.yml +++ b/tests/perf.yml @@ -16,13 +16,16 @@ connections: "{{ connstrs.results | map(attribute='ansible_facts.connstr') | join }}" - name: copy transfers binary - copy: src=perf/perf.linux dest=~/perf mode=0755 + copy: src=./perf/{{item}} dest=~/{{item}} mode=0755 + with_items: + - "perf.go" + - "transfers.go" - hosts: clients[0] gather_facts: no tasks: - name: fill the databases - shell: "~/perf {{connections}} -g -i" + shell: "go run ~/perf.go ~/transfers.go {{connections}} -g -i" register: transfers_result - debug: "var=transfers_result" @@ -30,7 +33,7 @@ gather_facts: no tasks: - name: run transfers - shell: "~/perf {{connections}} {{runkeys | d('-g -w 8 -r 1 -n 1000 -a 10000')}}" + shell: "go run ~/perf.go ~/transfers.go {{connections}} {{runkeys | d('-g -w 400 -r 1 -n 1000 -a 100000')}}" register: transfers_result - debug: var=transfers_result From dfd867005d1acfd3288d01ee169f9f5aa3b4a0ad Mon Sep 17 00:00:00 2001 From: Konstantin Knizhnik Date: Fri, 6 Nov 2015 20:22:35 +0300 Subject: [PATCH 21/46] Undo Assert --- pg_dtm.c | 1 - 1 file changed, 1 deletion(-) diff --git a/pg_dtm.c b/pg_dtm.c index 9c559e3..51e84ad 100644 --- a/pg_dtm.c +++ b/pg_dtm.c @@ -405,7 +405,6 @@ static TransactionId DtmAdjustOldestXid(TransactionId xid) } } if (prev != NULL) { - *(int*)0 = 0; local->trans_list_head = prev; xid = prev->xid; } else { From f17aa84a8776dc4ef469dead762eb0d6b4f09a64 Mon Sep 17 00:00:00 2001 From: knizhnik Date: Sun, 8 Nov 2015 00:35:42 +0300 Subject: [PATCH 22/46] Add dtmbench --- tests/dtmbench.cpp | 273 ++++++++++++++++++++++++++++++++++++++++ tests/makefile | 10 ++ tests/perf/perf.go | 15 +++ tests/perf/run.sh | 5 + tests/perf/transfers.go | 50 +++++--- tests/run.sh | 5 + 6 files changed, 338 insertions(+), 20 deletions(-) create mode 100644 tests/dtmbench.cpp create mode 100644 tests/makefile create mode 100755 tests/perf/run.sh create mode 100755 tests/run.sh diff --git a/tests/dtmbench.cpp b/tests/dtmbench.cpp new file mode 100644 index 0000000..af4b421 --- /dev/null +++ b/tests/dtmbench.cpp @@ -0,0 +1,273 @@ +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +using namespace std; +using namespace pqxx; + +template +class unique_ptr +{ + T* ptr; + + public: + unique_ptr(T* p = NULL) : ptr(p) {} + ~unique_ptr() { delete ptr; } + T& operator*() { return *ptr; } + T* operator->() { return ptr; } + void operator=(T* p) { ptr = p; } + void operator=(unique_ptr& other) { + ptr = other.ptr; + other.ptr = NULL; + } +}; + +typedef void* (*thread_proc_t)(void*); +typedef int64_t csn_t; + +struct thread +{ + pthread_t t; + size_t proceeded; + int id; + + void start(int tid, thread_proc_t proc) { + id = tid; + proceeded = 0; + pthread_create(&t, NULL, proc, this); + } + + void wait() { + pthread_join(t, NULL); + } +}; + +struct config +{ + int nReaders; + int nWriters; + int nIterations; + int nAccounts; + vector connections; + + config() { + nReaders = 1; + nWriters = 10; + nIterations = 1000; + nAccounts = 1000; + } +}; + +config cfg; +bool running; + +#define USEC 1000000 + +static time_t getCurrentTime() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + return (time_t)tv.tv_sec*USEC + tv.tv_usec; +} + + +void exec(transaction_base& txn, char const* sql, ...) +{ + va_list args; + va_start(args, sql); + char buf[1024]; + vsprintf(buf, sql, args); + va_end(args); + txn.exec(buf); +} + +int64_t execQuery( transaction_base& txn, char const* sql, ...) +{ + va_list args; + va_start(args, sql); + char buf[1024]; + vsprintf(buf, sql, args); + va_end(args); + result r = txn.exec(buf); + return r[0][0].as(int64_t()); +} + +void* reader(void* arg) +{ + thread& t = *(thread*)arg; + vector< unique_ptr > conns(cfg.connections.size()); + for (size_t i = 0; i < conns.size(); i++) { + conns[i] = new connection(cfg.connections[i]); + } + int64_t prevSum = 0; + + while (running) { + csn_t snapshot; + vector< unique_ptr > txns(conns.size()); + for (size_t i = 0; i < conns.size(); i++) { + txns[i] = new work(*conns[i]); + } + for (size_t i = 0; i < txns.size(); i++) { + if (i == 0) { + snapshot = execQuery(*txns[i], "select dtm_extend()"); + } else { + snapshot = execQuery(*txns[i], "select dtm_access(%ld)", snapshot); + } + } + int64_t sum = 0; + for (size_t i = 0; i < txns.size(); i++) { + sum += execQuery(*txns[i], "select sum(v) from t"); + } + if (sum != prevSum) { + printf("Total=%ld snapshot=%ld\n", sum, snapshot); + prevSum = sum; + } + t.proceeded += 1; + } + return NULL; +} + +void* writer(void* arg) +{ + thread& t = *(thread*)arg; + vector< unique_ptr > conns(cfg.connections.size()); + for (size_t i = 0; i < conns.size(); i++) { + conns[i] = new connection(cfg.connections[i]); + } + for (int i = 0; i < cfg.nIterations; i++) + { + char gtid[32]; + int srcCon, dstCon; + int srcAcc = (random() % ((cfg.nAccounts-cfg.nWriters)/cfg.nWriters))*cfg.nWriters + t.id; + int dstAcc = (random() % ((cfg.nAccounts-cfg.nWriters)/cfg.nWriters))*cfg.nWriters + t.id; + + sprintf(gtid, "%d.%d", t.id, i); + + do { + srcCon = random() % cfg.connections.size(); + dstCon = random() % cfg.connections.size(); + } while (srcCon == dstCon); + + nontransaction srcTx(*conns[srcCon]); + nontransaction dstTx(*conns[dstCon]); + + exec(srcTx, "begin transaction"); + exec(dstTx, "begin transaction"); + + csn_t snapshot = execQuery(srcTx, "select dtm_extend('%s')", gtid); + snapshot = execQuery(dstTx, "select dtm_access(%ld, '%s')", snapshot, gtid); + + exec(srcTx, "update t set v = v - 1 where u=%d", srcAcc); + exec(dstTx, "update t set v = v + 1 where u=%d", dstAcc); + + exec(srcTx, "prepare transaction '%s'", gtid); + exec(dstTx, "prepare transaction '%s'", gtid); + exec(srcTx, "select dtm_begin_prepare('%s')", gtid); + exec(dstTx, "select dtm_begin_prepare('%s')", gtid); + csn_t csn = execQuery(srcTx, "select dtm_prepare('%s', 0)", gtid); + csn = execQuery(dstTx, "select dtm_prepare('%s', %ld)", gtid, csn); + exec(srcTx, "select dtm_end_prepare('%s', %ld)", gtid, csn); + exec(dstTx, "select dtm_end_prepare('%s', %ld)", gtid, csn); + exec(srcTx, "commit prepared '%s'", gtid); + exec(dstTx, "commit prepared '%s'", gtid); + + t.proceeded += 1; + } + return NULL; +} + +void initializeDatabase() +{ + for (size_t i = 0; i < cfg.connections.size(); i++) { + connection conn(cfg.connections[i]); + work txn(conn); + exec(txn, "drop extension if exists pg_dtm"); + exec(txn, "create extension pg_dtm"); + exec(txn, "drop table if exists t"); + exec(txn, "create table t(u int primary key, v int)"); + exec(txn, "insert into t (select generate_series(0,%d), %d)", cfg.nAccounts, 0); + txn.commit(); + } +} + +int main (int argc, char* argv[]) +{ + bool initialize = false; + for (int i = 1; i < argc; i++) { + if (argv[i][0] == '-') { + switch (argv[i][1]) { + case 'r': + cfg.nReaders = atoi(argv[++i]); + continue; + case 'w': + cfg.nWriters = atoi(argv[++i]); + continue; + case 'a': + cfg.nAccounts = atoi(argv[++i]); + continue; + case 'n': + cfg.nIterations = atoi(argv[++i]); + continue; + case 'c': + cfg.connections.push_back(string(argv[++i])); + continue; + case 'i': + initialize = true; + continue; + } + } + printf("Options:\n" + "\t-r N\tnumber of readers (1)\n" + "\t-w N\tnumber of writers (10)\n" + "\t-a N\tnumber of accounts (1000)\n" + "\t-n N\tnumber of iterations (1000)\n" + "\t-c STR\tdatabase connection string\n" + "\t-i\tinitialize datanase\n"); + return 1; + } + if (initialize) { + initializeDatabase(); + } + + time_t start = getCurrentTime(); + running = true; + + vector readers(cfg.nReaders); + vector writers(cfg.nWriters); + size_t nReads = 0; + size_t nWrites = 0; + + for (int i = 0; i < cfg.nReaders; i++) { + readers[i].start(i, reader); + } + for (int i = 0; i < cfg.nWriters; i++) { + writers[i].start(i, writer); + } + + for (int i = 0; i < cfg.nWriters; i++) { + writers[i].wait(); + nWrites += writers[i].proceeded; + } + + running = false; + + for (int i = 0; i < cfg.nReaders; i++) { + readers[i].wait(); + nReads += writers[i].proceeded; + } + + time_t elapsed = getCurrentTime() - start; + printf("TPS(updates)=%f, TPS(selects)=%f\n", (double)(nWrites*USEC)/elapsed, (double)(nReads*USEC)/elapsed); + return 0; +} diff --git a/tests/makefile b/tests/makefile new file mode 100644 index 0000000..bcd7ee6 --- /dev/null +++ b/tests/makefile @@ -0,0 +1,10 @@ +CXX=g++ +CXXFLAGS=-g -Wall -O2 -pthread + +all: dtmbench + +dtmbench: dtmbench.cpp + $(CXX) $(CXXFLAGS) -o dtmbench dtmbench.cpp -lpqxx + +clean: + rm -f dtmbench \ No newline at end of file diff --git a/tests/perf/perf.go b/tests/perf/perf.go index 42bef7b..302aa8c 100644 --- a/tests/perf/perf.go +++ b/tests/perf/perf.go @@ -6,7 +6,9 @@ import ( "os" "sync" "time" + "runtime" "github.com/jackc/pgx" + "runtime/pprof" ) type ConnStrings []string @@ -28,6 +30,7 @@ var cfg struct { AccountsNum int ReadersNum int IterNum int + Profile string Writers struct { Num int @@ -99,6 +102,7 @@ func init() { "Show progress and other stuff for mortals") flag.BoolVar(&cfg.Parallel, "p", false, "Use parallel execs") + flag.StringVar(&cfg.Profile, "cpuprofile", "", "write cpu profile to file") repread := flag.Bool("l", false, "Use 'repeatable read' isolation level instead of 'read committed'") flag.Parse() @@ -129,6 +133,17 @@ func main() { fmt.Println("ERROR: This test needs at leas two connections") os.Exit(1) } + runtime.GOMAXPROCS(100) + + if cfg.Profile != "" { + f, err := os.Create(cfg.Profile) + if err != nil { + fmt.Println("Failed to create profile file") + os.Exit(1) + } + pprof.StartCPUProfile(f) + defer pprof.StopCPUProfile() + } // switch cfg.Backend { // case "transfers": diff --git a/tests/perf/run.sh b/tests/perf/run.sh new file mode 100755 index 0000000..4056ec3 --- /dev/null +++ b/tests/perf/run.sh @@ -0,0 +1,5 @@ +go run *.go \ +-C "dbname=postgres user=knizhnik port=5432 sslmode=disable" \ +-C "dbname=postgres user=knizhnik port=5433 sslmode=disable" \ +-C "dbname=postgres user=knizhnik port=5434 sslmode=disable" \ +-g -n 1000 -a 1000 -w 10 -r 1 $* diff --git a/tests/perf/transfers.go b/tests/perf/transfers.go index 90d762c..1fb1a62 100644 --- a/tests/perf/transfers.go +++ b/tests/perf/transfers.go @@ -47,6 +47,7 @@ func (t TransfersTS) writer(id int, cCommits chan int, cAborts chan int, wg *syn var nGlobalTrans = 0 var snapshot int64 var csn int64 + nWriters := cfg.Writers.Num if len(cfg.ConnStrs) == 1 { cfg.ConnStrs.Set(cfg.ConnStrs[0]) @@ -63,36 +64,45 @@ func (t TransfersTS) writer(id int, cCommits chan int, cAborts chan int, wg *syn for i := 0; i < cfg.IterNum; i++ { - - gtid := strconv.Itoa(id) + "." + strconv.Itoa(i) amount := 2*rand.Intn(2) - 1 - from_acc := rand.Intn(cfg.AccountsNum)//cfg.Writers.StartId + 2*id + 1 - to_acc := rand.Intn(cfg.AccountsNum)//cfg.Writers.StartId + 2*id + 2 - + //from_acc := cfg.Writers.StartId + 2*id + 1 + //to_acc := cfg.Writers.StartId + 2*id + 2 + from_acc := rand.Intn((cfg.AccountsNum-nWriters)/nWriters)*nWriters+id + to_acc := rand.Intn((cfg.AccountsNum-nWriters)/nWriters)*nWriters+id + + conn1 := conns[rand.Intn(len(conns))] conn2 := conns[rand.Intn(len(conns))] + for conn1 == conn2 { - conn1 = conns[rand.Intn(len(conns))] - conn2 = conns[rand.Intn(len(conns))] - } + conn1 = conns[rand.Intn(len(conns))] + conn2 = conns[rand.Intn(len(conns))] + } exec(conn1, "begin transaction") exec(conn2, "begin transaction") - snapshot = _execQuery(conn1, "select dtm_extend($1)", gtid) - snapshot = _execQuery(conn2, "select dtm_access($1, $2)", snapshot, gtid) + if cfg.UseDtm { + snapshot = _execQuery(conn1, "select dtm_extend($1)", gtid) + snapshot = _execQuery(conn2, "select dtm_access($1, $2)", snapshot, gtid) + } exec(conn1, "update t set v = v - $1 where u=$2", amount, from_acc) exec(conn2, "update t set v = v + $1 where u=$2", amount, to_acc) - exec(conn1, "prepare transaction '" + gtid + "'") - exec(conn2, "prepare transaction '" + gtid + "'") - exec(conn1, "select dtm_begin_prepare($1)", gtid) - exec(conn2, "select dtm_begin_prepare($1)", gtid) - csn = _execQuery(conn1, "select dtm_prepare($1, 0)", gtid) - csn = _execQuery(conn2, "select dtm_prepare($1, $2)", gtid, csn) - exec(conn1, "select dtm_end_prepare($1, $2)", gtid, csn) - exec(conn2, "select dtm_end_prepare($1, $2)", gtid, csn) - exec(conn1, "commit prepared '" + gtid + "'") - exec(conn2, "commit prepared '" + gtid + "'") + if cfg.UseDtm { + exec(conn1, "prepare transaction '" + gtid + "'") + exec(conn2, "prepare transaction '" + gtid + "'") + exec(conn1, "select dtm_begin_prepare($1)", gtid) + exec(conn2, "select dtm_begin_prepare($1)", gtid) + csn = _execQuery(conn1, "select dtm_prepare($1, 0)", gtid) + csn = _execQuery(conn2, "select dtm_prepare($1, $2)", gtid, csn) + exec(conn1, "select dtm_end_prepare($1, $2)", gtid, csn) + exec(conn2, "select dtm_end_prepare($1, $2)", gtid, csn) + exec(conn1, "commit prepared '" + gtid + "'") + exec(conn2, "commit prepared '" + gtid + "'") + } else { + exec(conn1, "commit") + exec(conn2, "commit") + } nGlobalTrans++ } diff --git a/tests/run.sh b/tests/run.sh new file mode 100755 index 0000000..6b9f342 --- /dev/null +++ b/tests/run.sh @@ -0,0 +1,5 @@ +./dtmbench \ +-c "dbname=postgres host=localhost user=knizhnik port=5432 sslmode=disable" \ +-c "dbname=postgres host=localhost user=knizhnik port=5433 sslmode=disable" \ +-c "dbname=postgres host=localhost user=knizhnik port=5434 sslmode=disable" \ +-n 1000 -a 1000 -w 10 -r 1 $* From ed4f3e360000d24f693f2aa1c507dd96c4c09da5 Mon Sep 17 00:00:00 2001 From: knizhnik Date: Sun, 8 Nov 2015 11:55:25 +0300 Subject: [PATCH 23/46] Fix bugs in dtmbench --- tests/dtmbench.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/dtmbench.cpp b/tests/dtmbench.cpp index af4b421..fe6c71d 100644 --- a/tests/dtmbench.cpp +++ b/tests/dtmbench.cpp @@ -196,7 +196,7 @@ void initializeDatabase() exec(txn, "create extension pg_dtm"); exec(txn, "drop table if exists t"); exec(txn, "create table t(u int primary key, v int)"); - exec(txn, "insert into t (select generate_series(0,%d), %d)", cfg.nAccounts, 0); + exec(txn, "insert into t (select generate_series(0,%d), %d)", cfg.nAccounts-1, 0); txn.commit(); } } @@ -264,7 +264,7 @@ int main (int argc, char* argv[]) for (int i = 0; i < cfg.nReaders; i++) { readers[i].wait(); - nReads += writers[i].proceeded; + nReads += readers[i].proceeded; } time_t elapsed = getCurrentTime() - start; From 754e495d6281335c190a247bcd9380074c3561a5 Mon Sep 17 00:00:00 2001 From: Stas Kelvich Date: Mon, 9 Nov 2015 12:34:49 +0300 Subject: [PATCH 24/46] perf.go: do not produce unused connections --- tests/perf.yml | 2 +- tests/perf/transfers.go | 66 ++++++++++++++++++++++++++--------------- 2 files changed, 43 insertions(+), 25 deletions(-) diff --git a/tests/perf.yml b/tests/perf.yml index 35f1402..0a5442a 100644 --- a/tests/perf.yml +++ b/tests/perf.yml @@ -33,7 +33,7 @@ gather_facts: no tasks: - name: run transfers - shell: "go run ~/perf.go ~/transfers.go {{connections}} {{runkeys | d('-g -w 400 -r 1 -n 1000 -a 100000')}}" + shell: "go run ~/perf.go ~/transfers.go {{connections}} {{runkeys | d('-g -w 200 -r 1 -n 1000 -a 100000')}}" register: transfers_result - debug: var=transfers_result diff --git a/tests/perf/transfers.go b/tests/perf/transfers.go index 90d762c..78cb9c7 100644 --- a/tests/perf/transfers.go +++ b/tests/perf/transfers.go @@ -43,7 +43,6 @@ func (t TransfersTS) prepare_one(connstr string, wg *sync.WaitGroup) { } func (t TransfersTS) writer(id int, cCommits chan int, cAborts chan int, wg *sync.WaitGroup) { - var conns []*pgx.Conn var nGlobalTrans = 0 var snapshot int64 var csn int64 @@ -52,45 +51,64 @@ func (t TransfersTS) writer(id int, cCommits chan int, cAborts chan int, wg *syn cfg.ConnStrs.Set(cfg.ConnStrs[0]) } - for _, connstr := range cfg.ConnStrs { - dbconf, err := pgx.ParseDSN(connstr) - checkErr(err) - conn, err := pgx.Connect(dbconf) - checkErr(err) - defer conn.Close() - conns = append(conns, conn) - } + // for _, connstr := range cfg.ConnStrs { + // dbconf, err := pgx.ParseDSN(connstr) + // checkErr(err) + // conn, err := pgx.Connect(dbconf) + // checkErr(err) + // defer conn.Close() + // conns = append(conns, conn) + // } + + dbconf1, err := pgx.ParseDSN(cfg.ConnStrs[ id % len(cfg.ConnStrs) ]) + checkErr(err) + conn1, err := pgx.Connect(dbconf1) + checkErr(err) + defer conn1.Close() + + dbconf2, err := pgx.ParseDSN(cfg.ConnStrs[ (id + 1) % len(cfg.ConnStrs) ]) + checkErr(err) + conn2, err := pgx.Connect(dbconf2) + checkErr(err) + defer conn2.Close() for i := 0; i < cfg.IterNum; i++ { - gtid := strconv.Itoa(id) + "." + strconv.Itoa(i) amount := 2*rand.Intn(2) - 1 from_acc := rand.Intn(cfg.AccountsNum)//cfg.Writers.StartId + 2*id + 1 to_acc := rand.Intn(cfg.AccountsNum)//cfg.Writers.StartId + 2*id + 2 - conn1 := conns[rand.Intn(len(conns))] - conn2 := conns[rand.Intn(len(conns))] - for conn1 == conn2 { - conn1 = conns[rand.Intn(len(conns))] - conn2 = conns[rand.Intn(len(conns))] - } + // conn1 := conns[rand.Intn(len(conns))] + // conn2 := conns[rand.Intn(len(conns))] + // for conn1 == conn2 { + // conn1 = conns[rand.Intn(len(conns))] + // conn2 = conns[rand.Intn(len(conns))] + // } exec(conn1, "begin transaction") exec(conn2, "begin transaction") - snapshot = _execQuery(conn1, "select dtm_extend($1)", gtid) - snapshot = _execQuery(conn2, "select dtm_access($1, $2)", snapshot, gtid) + + if cfg.UseDtm { + snapshot = _execQuery(conn1, "select dtm_extend($1)", gtid) + snapshot = _execQuery(conn2, "select dtm_access($1, $2)", snapshot, gtid) + } + exec(conn1, "update t set v = v - $1 where u=$2", amount, from_acc) exec(conn2, "update t set v = v + $1 where u=$2", amount, to_acc) exec(conn1, "prepare transaction '" + gtid + "'") exec(conn2, "prepare transaction '" + gtid + "'") - exec(conn1, "select dtm_begin_prepare($1)", gtid) - exec(conn2, "select dtm_begin_prepare($1)", gtid) - csn = _execQuery(conn1, "select dtm_prepare($1, 0)", gtid) - csn = _execQuery(conn2, "select dtm_prepare($1, $2)", gtid, csn) - exec(conn1, "select dtm_end_prepare($1, $2)", gtid, csn) - exec(conn2, "select dtm_end_prepare($1, $2)", gtid, csn) + + if cfg.UseDtm { + exec(conn1, "select dtm_begin_prepare($1)", gtid) + exec(conn2, "select dtm_begin_prepare($1)", gtid) + csn = _execQuery(conn1, "select dtm_prepare($1, 0)", gtid) + csn = _execQuery(conn2, "select dtm_prepare($1, $2)", gtid, csn) + exec(conn1, "select dtm_end_prepare($1, $2)", gtid, csn) + exec(conn2, "select dtm_end_prepare($1, $2)", gtid, csn) + } + exec(conn1, "commit prepared '" + gtid + "'") exec(conn2, "commit prepared '" + gtid + "'") nGlobalTrans++ From 5c4cded2c2aca737fd6454545b59e95fbfe9c80b Mon Sep 17 00:00:00 2001 From: Konstantin Knizhnik Date: Mon, 9 Nov 2015 14:21:43 +0300 Subject: [PATCH 25/46] Auto adjust time --- pg_dtm.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/pg_dtm.c b/pg_dtm.c index 51e84ad..fd8a779 100644 --- a/pg_dtm.c +++ b/pg_dtm.c @@ -54,6 +54,7 @@ typedef struct DtmTransStatus typedef struct { cid_t cid; + long time_shift; volatile slock_t lock; DtmTransStatus* trans_list_head; DtmTransStatus** trans_list_tail; @@ -105,7 +106,7 @@ static timestamp_t dtm_get_current_time() { struct timeval tv; gettimeofday(&tv, NULL); - return (timestamp_t)tv.tv_sec*USEC + tv.tv_usec; + return (timestamp_t)tv.tv_sec*USEC + tv.tv_usec + local->time_shift; } static void dtm_sleep(timestamp_t interval) @@ -136,6 +137,11 @@ static cid_t dtm_get_cid() static cid_t dtm_sync(cid_t global_cid) { cid_t local_cid; +#if 1 + while ((local_cid = dtm_get_cid()) < global_cid) { + local->time_shift += global_cid - local_cid; + } +#else while ((local_cid = dtm_get_cid()) < global_cid) { SpinLockRelease(&local->lock); #if TRACE_SLEEP_TIME @@ -160,6 +166,7 @@ static cid_t dtm_sync(cid_t global_cid) #endif SpinLockAcquire(&local->lock); } +#endif return global_cid; } @@ -525,6 +532,7 @@ void DtmInitialize() local = (DtmNodeState*)ShmemInitStruct("dtm", sizeof(DtmNodeState), &found); if (!found) { + local->time_shift = 0; local->cid = dtm_get_current_time(); local->trans_list_head = NULL; local->trans_list_tail = &local->trans_list_head; From baa904606b3fd85c196a2f8fdb75166e718f926b Mon Sep 17 00:00:00 2001 From: Stas Kelvich Date: Tue, 10 Nov 2015 20:31:21 +0300 Subject: [PATCH 26/46] change deploy directory structure; change dtmbench output format to json; --- tests/deploy/cluster.yml | 13 ++++++------ tests/deploy/roles/postgres/tasks/main.yml | 4 ++++ tests/deploy/roles/postgres/vars/main.yml | 23 ++++------------------ tests/dtmbench.cpp | 15 +++++++++++++- tests/perf.yml | 22 ++++++++++++--------- 5 files changed, 42 insertions(+), 35 deletions(-) diff --git a/tests/deploy/cluster.yml b/tests/deploy/cluster.yml index 6398609..d060bd2 100644 --- a/tests/deploy/cluster.yml +++ b/tests/deploy/cluster.yml @@ -9,7 +9,6 @@ pg_repo: https://github.com/kelvich/postgresql.git pg_version_tag: xtm_patched pg_destroy_and_init: true - pg_datadir: ./postgrespro-data pg_config_role: - line: "dtm.vacuum_delay=60" @@ -17,24 +16,26 @@ - name: clone dtm sources git: repo=https://github.com/postgrespro/pg_tsdtm.git - dest=./pg_tsdtm + dest={{pg_prefix}}/pg_tsdtm accept_hostkey=yes update=yes force=yes register: dtm_sources - name: build dtm - shell: "PG_CONFIG={{pg_dst}}/bin/pg_config make clean && PG_CONFIG={{pg_dst}}/bin/pg_config make -j {{makejobs}} install" + shell: "make clean && make -j {{makejobs}} install" args: - chdir: ./pg_tsdtm + chdir: "{{pg_prefix}}/pg_tsdtm" + environment: + PG_CONFIG: "{{pg_dst}}/bin/pg_config" when: dtm_sources.changed - name: enable dtm extension on datanodes lineinfile: dest: "{{pg_datadir}}/postgresql.conf" - regexp: "^shared_preload_libraries " + regexp: "^shared_preload_libraries" line: "shared_preload_libraries = 'pg_dtm'" state: present - name: restart postgrespro - command: "{{pg_dst}}/bin/pg_ctl restart -w -D ./postgrespro-data -l ./postgrespro-data/pg.log" + command: "{{pg_dst}}/bin/pg_ctl restart -w -D {{pg_datadir}} -l {{pg_datadir}}/pg.log" diff --git a/tests/deploy/roles/postgres/tasks/main.yml b/tests/deploy/roles/postgres/tasks/main.yml index 6df0e0d..e692175 100644 --- a/tests/deploy/roles/postgres/tasks/main.yml +++ b/tests/deploy/roles/postgres/tasks/main.yml @@ -30,6 +30,10 @@ when: ansible_os_family == "RedHat" sudo: yes +- name: increase semaphores + shell: sysctl kernel.sem='1000 128000 128 512' + sudo: yes + - name: clone postgres sources git: repo={{pg_repo}} dest={{pg_src}} diff --git a/tests/deploy/roles/postgres/vars/main.yml b/tests/deploy/roles/postgres/vars/main.yml index 2a73cea..982cc42 100644 --- a/tests/deploy/roles/postgres/vars/main.yml +++ b/tests/deploy/roles/postgres/vars/main.yml @@ -2,17 +2,11 @@ --- makejobs: 4 -deploy_postgres: false -deploy_dtm: false -deploy_pg_shard: false - pg_repo: git://git.postgresql.org/git/postgresql.git pg_version_tag: master - pg_destroy_and_init: false - pg_port: 5432 pg_dtm_enable: false pg_dtm_host: "127.0.0.1" @@ -27,18 +21,9 @@ pg_config: - line: "port = {{pg_port}}" pg_config_role: - line: "#pg_config_role" -pg_src: ~/postgrespro -pg_dst: /tmp/postgrespro-build -pg_datadir: ~/postgrespro-data - -libuv: - version: v1.7.5 - src: ./libuv - dst: /tmp/libuv-build -dtmd: - port: 5431 - dst: ./dtmd - datadir: ./dtmd-data - log: ./dtmd.log +pg_prefix: "{{ansible_env.HOME}}/pg_cluster" +pg_src: "{{pg_prefix}}/src" +pg_dst: "{{pg_prefix}}/install" +pg_datadir: "{{pg_prefix}}/data_{{pg_port}}" diff --git a/tests/dtmbench.cpp b/tests/dtmbench.cpp index 71548be..4baefc3 100644 --- a/tests/dtmbench.cpp +++ b/tests/dtmbench.cpp @@ -271,6 +271,19 @@ int main (int argc, char* argv[]) } time_t elapsed = getCurrentTime() - start; - printf("TPS(updates)=%f, TPS(selects)=%f\n", (double)(nWrites*USEC)/elapsed, (double)(nReads*USEC)/elapsed); + + + + printf( + "{\"update_tps\":%f, \"read_tps\":%f, \"readers\":%d, \"writers\":%d, \"accounts\":%d, \"iterations\":%d, \"hosts\":%d}\n", + (double)(nWrites*USEC)/elapsed, + (double)(nReads*USEC)/elapsed, + cfg.nReaders, + cfg.nWriters, + cfg.nAccounts, + cfg.nIterations, + cfg.connections.size() + ); + return 0; } diff --git a/tests/perf.yml b/tests/perf.yml index ab31ba0..387f82d 100644 --- a/tests/perf.yml +++ b/tests/perf.yml @@ -1,6 +1,6 @@ --- -- hosts: clients[0] +- hosts: clients gather_facts: no tasks: @@ -15,21 +15,25 @@ set_fact: connections: "{{ connstrs.results | map(attribute='ansible_facts.connstr') | join }}" - - name: copy transfers binary + # - name: copy transfers binary + # copy: src=./{{item}} dest=~/{{item}} mode=0755 + # with_items: + # - "dtmbench" + # - "libpqxx-4.0.so" + + - name: copy transfers source copy: src=./{{item}} dest=~/{{item}} mode=0755 with_items: - "dtmbench.cpp" - name: compile dtmbench - shell: "g++ -g -Wall -O2 -o dtmbench dtmbench.cpp -lpqxx -pthread " + shell: "g++ -g -Wall -O2 -o dtmbench dtmbench.cpp -lpqxx -pthread" -- hosts: clients[0] - gather_facts: no - tasks: - name: run transfers - shell: "./dtmbench {{connections}} -w {{item}} -r 1 -n 1000 -a 100000 -i " + shell: "./dtmbench {{connections}} -w {{item}} -r 1 -n 100 -a 100000 -i " register: transfers_result - with_sequence: start=20 end=400 stride=20 + with_sequence: start=100 end=200 stride=100 - - debug: msg={{transfers_result.results | map(attribute='stdout_lines') | join }} + - local_action: shell echo "{{transfers_result.results | map(attribute='stdout') | join('\n')}}" >> x.out + - debug: msg="{{ transfers_result.results | map(attribute='stdout') | join('\n') }}" From 7b4257c530b3af523296d75ff90b9947606eb4a4 Mon Sep 17 00:00:00 2001 From: Stas Kelvich Date: Tue, 10 Nov 2015 22:35:39 +0300 Subject: [PATCH 27/46] ability to copy compiled postgres instead of building it --- tests/deploy/cluster.yml | 38 ++++++++++--------- tests/deploy/roles/postgres/tasks/main.yml | 43 ++++++++++++++-------- 2 files changed, 49 insertions(+), 32 deletions(-) diff --git a/tests/deploy/cluster.yml b/tests/deploy/cluster.yml index d060bd2..e0bf808 100644 --- a/tests/deploy/cluster.yml +++ b/tests/deploy/cluster.yml @@ -1,34 +1,38 @@ --- - hosts: nodes + # gather_facts: no + # pre_tasks: + # - name: make a list + # set_fact: + # ansible_os_family: "Debian" roles: - - role: postgres pg_port: 15432 pg_repo: https://github.com/kelvich/postgresql.git pg_version_tag: xtm_patched pg_destroy_and_init: true + pg_copydist: true pg_config_role: - line: "dtm.vacuum_delay=60" tasks: - - - name: clone dtm sources - git: repo=https://github.com/postgrespro/pg_tsdtm.git - dest={{pg_prefix}}/pg_tsdtm - accept_hostkey=yes - update=yes - force=yes - register: dtm_sources - - - name: build dtm - shell: "make clean && make -j {{makejobs}} install" - args: - chdir: "{{pg_prefix}}/pg_tsdtm" - environment: - PG_CONFIG: "{{pg_dst}}/bin/pg_config" - when: dtm_sources.changed + # - name: clone dtm sources + # git: repo=https://github.com/postgrespro/pg_tsdtm.git + # dest={{pg_prefix}}/pg_tsdtm + # accept_hostkey=yes + # update=yes + # force=yes + # register: dtm_sources + + # - name: build dtm + # shell: "make clean && make -j {{makejobs}} install" + # args: + # chdir: "{{pg_prefix}}/pg_tsdtm" + # environment: + # PG_CONFIG: "{{pg_dst}}/bin/pg_config" + # when: dtm_sources.changed - name: enable dtm extension on datanodes lineinfile: diff --git a/tests/deploy/roles/postgres/tasks/main.yml b/tests/deploy/roles/postgres/tasks/main.yml index e692175..d813e09 100644 --- a/tests/deploy/roles/postgres/tasks/main.yml +++ b/tests/deploy/roles/postgres/tasks/main.yml @@ -15,7 +15,7 @@ - name: ensure dependencies (RedHat) yum: name="@Development tools" state=present - when: ansible_os_family == "RedHat" + when: (pg_copydist is undefined) and ansible_os_family == "RedHat" sudo: yes - name: ensure dependencies (RedHat) @@ -27,13 +27,15 @@ - bison - flex - readline-devel - when: ansible_os_family == "RedHat" + when: (pg_copydist is undefined) and ansible_os_family == "RedHat" sudo: yes - name: increase semaphores shell: sysctl kernel.sem='1000 128000 128 512' sudo: yes +############################################################################# + - name: clone postgres sources git: repo={{pg_repo}} dest={{pg_src}} @@ -41,25 +43,39 @@ depth=1 accept_hostkey=True register: pg_sources - -############################################################################# - -- stat: path={{pg_datadir}}/postmaster.pid - register: pg_pidfile - -- name: stop postgres if it was running - command: "{{pg_dst}}/bin/pg_ctl stop -w -D {{pg_datadir}}" - when: pg_pidfile.stat.exists + when: pg_copydist is undefined - name: force rebuild on changed sources command: "rm -f {{pg_dst}}/bin/postgres" - when: pg_sources.changed + when: (pg_copydist is undefined) and pg_sources.changed - name: build and install shell: ./configure --prefix={{pg_dst}} --without-zlib && make clean && make -j {{makejobs}} && make install args: chdir: "{{pg_src}}" creates: "{{pg_dst}}/bin/postgres" + when: pg_copydist is undefined + +############################################################################# + +- name: copy pg source + copy: src=./{{item}} dest=~/{{item}} mode=0755 + with_items: + - "pg_cluster_install.tgz" + when: pg_copydist is defined + +- name: extract postgres + command: "tar xzf pg_cluster_install.tgz" + when: pg_copydist is defined + +############################################################################# + +- stat: path={{pg_datadir}}/postmaster.pid + register: pg_pidfile + +- name: stop postgres if it was running + command: "{{pg_dst}}/bin/pg_ctl stop -w -D {{pg_datadir}}" + when: pg_pidfile.stat.exists - name: remove datadirs on datanodes command: "rm -rf {{pg_datadir}}" @@ -89,9 +105,6 @@ dest: "{{pg_datadir}}/pg_hba.conf" line: "host all all 0.0.0.0/0 trust" -# - include: pg_shard.yml -# when: deploy_pg_shard - - name: start postgrespro command: "{{pg_dst}}/bin/pg_ctl start -w -D {{pg_datadir}} -l {{pg_datadir}}/pg.log" From a6e5d317668364a00ff97ca0b60eb181b300052f Mon Sep 17 00:00:00 2001 From: Stas Kelvich Date: Wed, 11 Nov 2015 16:44:24 +0300 Subject: [PATCH 28/46] dtmbench deploy on several servers --- tests/deploy/cluster.yml | 13 ++++ tests/deploy/hosts | 12 ++-- tests/deploy/roles/postgres/tasks/main.yml | 10 ++- tests/deploy/roles/postgres/vars/main.yml | 3 - tests/dtmbench.cpp | 80 +++++++++++++++------- tests/perf.yml | 34 +++++---- 6 files changed, 103 insertions(+), 49 deletions(-) diff --git a/tests/deploy/cluster.yml b/tests/deploy/cluster.yml index e0bf808..3397d66 100644 --- a/tests/deploy/cluster.yml +++ b/tests/deploy/cluster.yml @@ -43,3 +43,16 @@ - name: restart postgrespro command: "{{pg_dst}}/bin/pg_ctl restart -w -D {{pg_datadir}} -l {{pg_datadir}}/pg.log" + environment: + LD_LIBRARY_PATH: "{{pg_dst}}/lib/" + + +- hosts: clients + tasks: + - name: copy pg source + copy: src=./{{item}} dest=~/{{item}} mode=0755 + with_items: + - "pg_cluster_install.tgz" + + - name: extract postgres + command: "tar xzf pg_cluster_install.tgz" diff --git a/tests/deploy/hosts b/tests/deploy/hosts index c9d4501..a31b9db 100644 --- a/tests/deploy/hosts +++ b/tests/deploy/hosts @@ -1,12 +1,12 @@ [clients] -158.250.29.4 ansible_ssh_user=cluster offset=6001 -158.250.29.7 ansible_ssh_user=cluster ansible_ssh_port=2299 offset=3001 +158.250.29.4 ansible_ssh_user=cluster offset=600001 +158.250.29.7 ansible_ssh_user=cluster ansible_ssh_port=2299 offset=300001 [nodes] -158.250.29.5 ansible_ssh_user=cluster offset=5001 -158.250.29.6 ansible_ssh_user=cluster offset=4001 -158.250.29.8 ansible_ssh_user=cluster offset=2001 -158.250.29.9 ansible_ssh_user=cluster offset=1001 +158.250.29.5 ansible_ssh_user=cluster offset=500001 +158.250.29.6 ansible_ssh_user=cluster offset=400001 +158.250.29.8 ansible_ssh_user=cluster offset=200001 +158.250.29.9 ansible_ssh_user=cluster offset=100001 158.250.29.10 ansible_ssh_user=cluster offset=1 [master] diff --git a/tests/deploy/roles/postgres/tasks/main.yml b/tests/deploy/roles/postgres/tasks/main.yml index d813e09..f3b5d3c 100644 --- a/tests/deploy/roles/postgres/tasks/main.yml +++ b/tests/deploy/roles/postgres/tasks/main.yml @@ -75,6 +75,8 @@ - name: stop postgres if it was running command: "{{pg_dst}}/bin/pg_ctl stop -w -D {{pg_datadir}}" + environment: + LD_LIBRARY_PATH: "{{pg_dst}}/lib" when: pg_pidfile.stat.exists - name: remove datadirs on datanodes @@ -83,6 +85,8 @@ - name: create datadirs on datanodes command: "{{pg_dst}}/bin/initdb {{pg_datadir}}" + environment: + LD_LIBRARY_PATH: "{{pg_dst}}/lib/" args: creates: "{{pg_datadir}}" @@ -106,7 +110,7 @@ line: "host all all 0.0.0.0/0 trust" - name: start postgrespro - command: "{{pg_dst}}/bin/pg_ctl start -w -D {{pg_datadir}} -l {{pg_datadir}}/pg.log" - - + shell: "{{pg_dst}}/bin/pg_ctl start -w -D {{pg_datadir}} -l {{pg_datadir}}/pg.log" + environment: + LD_LIBRARY_PATH: "{{pg_dst}}/lib/" diff --git a/tests/deploy/roles/postgres/vars/main.yml b/tests/deploy/roles/postgres/vars/main.yml index 982cc42..45e948f 100644 --- a/tests/deploy/roles/postgres/vars/main.yml +++ b/tests/deploy/roles/postgres/vars/main.yml @@ -8,8 +8,6 @@ pg_version_tag: master pg_destroy_and_init: false pg_port: 5432 -pg_dtm_enable: false -pg_dtm_host: "127.0.0.1" pg_config: - line: "shared_buffers = 3GB" - line: "wal_keep_segments = 128" @@ -26,4 +24,3 @@ pg_prefix: "{{ansible_env.HOME}}/pg_cluster" pg_src: "{{pg_prefix}}/src" pg_dst: "{{pg_prefix}}/install" pg_datadir: "{{pg_prefix}}/data_{{pg_port}}" - diff --git a/tests/dtmbench.cpp b/tests/dtmbench.cpp index 4baefc3..ce3bcc5 100644 --- a/tests/dtmbench.cpp +++ b/tests/dtmbench.cpp @@ -59,13 +59,17 @@ struct config int nWriters; int nIterations; int nAccounts; + int startId; + int diapason; vector connections; config() { nReaders = 1; nWriters = 10; nIterations = 1000; - nAccounts = 1000; + nAccounts = 100000; + startId = 1; + diapason = 100000; } }; @@ -141,36 +145,41 @@ void* reader(void* arg) void* writer(void* arg) { thread& t = *(thread*)arg; - vector< unique_ptr > conns(cfg.connections.size()); - for (size_t i = 0; i < conns.size(); i++) { - conns[i] = new connection(cfg.connections[i]); - } + connection *srcCon, *dstCon; + + srcCon = new connection(cfg.connections[t.id % cfg.connections.size()]); + dstCon = new connection(cfg.connections[(t.id + 1) % cfg.connections.size()]); + for (int i = 0; i < cfg.nIterations; i++) { char gtid[32]; - int srcCon, dstCon; - int srcAcc = (random() % ((cfg.nAccounts-cfg.nWriters)/cfg.nWriters))*cfg.nWriters + t.id; - int dstAcc = (random() % ((cfg.nAccounts-cfg.nWriters)/cfg.nWriters))*cfg.nWriters + t.id; - sprintf(gtid, "%d.%d", t.id, i); + // int srcAcc = (random() % ((cfg.nAccounts-cfg.nWriters)/cfg.nWriters))*cfg.nWriters + t.id; + // int dstAcc = (random() % ((cfg.nAccounts-cfg.nWriters)/cfg.nWriters))*cfg.nWriters + t.id; - do { - srcCon = random() % cfg.connections.size(); - dstCon = random() % cfg.connections.size(); - } while (srcCon == dstCon); - - nontransaction srcTx(*conns[srcCon]); - nontransaction dstTx(*conns[dstCon]); + int srcAcc = cfg.startId + random() % cfg.diapason; + int dstAcc = cfg.startId + random() % cfg.diapason; + + if (srcAcc > dstAcc) { + int tmpAcc = dstAcc; + dstAcc = srcAcc; + srcAcc = tmpAcc; + } + + sprintf(gtid, "%d.%d.%d", cfg.startId, t.id, i); + + nontransaction srcTx(*srcCon); + nontransaction dstTx(*dstCon); exec(srcTx, "begin transaction"); exec(dstTx, "begin transaction"); csn_t snapshot = execQuery(srcTx, "select dtm_extend('%s')", gtid); snapshot = execQuery(dstTx, "select dtm_access(%ld, '%s')", snapshot, gtid); - + exec(srcTx, "update t set v = v - 1 where u=%d", srcAcc); exec(dstTx, "update t set v = v + 1 where u=%d", dstAcc); - + exec(srcTx, "prepare transaction '%s'", gtid); exec(dstTx, "prepare transaction '%s'", gtid); exec(srcTx, "select dtm_begin_prepare('%s')", gtid); @@ -196,17 +205,20 @@ void initializeDatabase() exec(txn, "create extension pg_dtm"); exec(txn, "drop table if exists t"); exec(txn, "create table t(u int primary key, v int)"); - exec(txn, "insert into t (select generate_series(0,%d), %d)", cfg.nAccounts-1, 0); + exec(txn, "insert into t (select generate_series(0,%d), %d)", cfg.nAccounts, 0); txn.commit(); - - // nontransaction vacTx(conn); - // exec(vacTx, "vacuum full"); } } int main (int argc, char* argv[]) { bool initialize = false; + + if (argc == 1){ + printf("Use -h to show usage options\n"); + return 1; + } + for (int i = 1; i < argc; i++) { if (argv[i][0] == '-') { switch (argv[i][1]) { @@ -222,6 +234,12 @@ int main (int argc, char* argv[]) case 'n': cfg.nIterations = atoi(argv[++i]); continue; + case 's': + cfg.startId = atoi(argv[++i]); + continue; + case 'd': + cfg.diapason = atoi(argv[++i]); + continue; case 'C': cfg.connections.push_back(string(argv[++i])); continue; @@ -233,14 +251,24 @@ int main (int argc, char* argv[]) printf("Options:\n" "\t-r N\tnumber of readers (1)\n" "\t-w N\tnumber of writers (10)\n" - "\t-a N\tnumber of accounts (1000)\n" + "\t-a N\tnumber of accounts (100000)\n" + "\t-s N\tperform updates starting from this id (1)\n" + "\t-d N\tperform updates in this diapason (100000)\n" "\t-n N\tnumber of iterations (1000)\n" - "\t-c STR\tdatabase connection string\n" + "\t-C STR\tdatabase connection string\n" "\t-i\tinitialize datanase\n"); return 1; } + + if (cfg.startId + cfg.diapason - 1 > cfg.nAccounts) { + printf("startId + diapason should be less that nAccounts. Exiting.\n"); + return 1; + } + if (initialize) { initializeDatabase(); + printf("%d account inserted\n", cfg.nAccounts); + return 0; } time_t start = getCurrentTime(); @@ -275,7 +303,9 @@ int main (int argc, char* argv[]) printf( - "{\"update_tps\":%f, \"read_tps\":%f, \"readers\":%d, \"writers\":%d, \"accounts\":%d, \"iterations\":%d, \"hosts\":%d}\n", + "{\"update_tps\":%f, \"read_tps\":%f," + " \"readers\":%d, \"writers\":%d," + " \"accounts\":%d, \"iterations\":%d, \"hosts\":%d}\n", (double)(nWrites*USEC)/elapsed, (double)(nReads*USEC)/elapsed, cfg.nReaders, diff --git a/tests/perf.yml b/tests/perf.yml index 387f82d..10c9656 100644 --- a/tests/perf.yml +++ b/tests/perf.yml @@ -6,7 +6,7 @@ - name: generate connstrings set_fact: - connstr: "-C 'host={{item}} user=cluster port=15432 dbname=postgres' " + connstr: "-C 'host={{item}} user={{ansible_ssh_user}} port=15432 dbname=postgres' " with_items: groups['nodes'] | reverse | batch(nnodes | d(2) | int) | first register: connstrs @@ -15,25 +15,35 @@ set_fact: connections: "{{ connstrs.results | map(attribute='ansible_facts.connstr') | join }}" - # - name: copy transfers binary + # - name: copy transfers source # copy: src=./{{item}} dest=~/{{item}} mode=0755 # with_items: - # - "dtmbench" - # - "libpqxx-4.0.so" + # - "dtmbench.cpp" - - name: copy transfers source - copy: src=./{{item}} dest=~/{{item}} mode=0755 - with_items: - - "dtmbench.cpp" + # - name: compile dtmbench + # shell: "g++ -g -Wall -O2 -o dtmbench dtmbench.cpp -lpqxx -lpq -pthread" + + # - name: compile dtmbench + # shell: "mv dtmbench ~/pg_cluster/install/bin/dtmbench" - - name: compile dtmbench - shell: "g++ -g -Wall -O2 -o dtmbench dtmbench.cpp -lpqxx -pthread" +- hosts: clients[0] + gather_facts: no + tasks: + - name: init database + shell: "~/pg_cluster/install/bin/dtmbench {{connections}} -a 1000000 -i" + register: init_result + - debug: var=init_result +- hosts: clients + gather_facts: no + tasks: - name: run transfers - shell: "./dtmbench {{connections}} -w {{item}} -r 1 -n 100 -a 100000 -i " + shell: "~/pg_cluster/install/bin/dtmbench {{connections}} -w {{item}} -s {{offset}} -d 100000 -r 1 -n 1000 -a 1000000" register: transfers_result + environment: + LD_LIBRARY_PATH: "/home/{{ansible_ssh_user}}/pg_cluster/install/lib" with_sequence: start=100 end=200 stride=100 - - local_action: shell echo "{{transfers_result.results | map(attribute='stdout') | join('\n')}}" >> x.out + - local_action: shell echo "{{transfers_result.results | map(attribute='stdout') | join('\n')}}" >> perf.results - debug: msg="{{ transfers_result.results | map(attribute='stdout') | join('\n') }}" From 8944b3ec99e111f3ff2bd4bd4ad1b398008ada0b Mon Sep 17 00:00:00 2001 From: Stas Kelvich Date: Wed, 11 Nov 2015 16:55:41 +0300 Subject: [PATCH 29/46] prepend hostname to results --- tests/perf.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/perf.yml b/tests/perf.yml index 10c9656..eee5e2f 100644 --- a/tests/perf.yml +++ b/tests/perf.yml @@ -38,7 +38,7 @@ gather_facts: no tasks: - name: run transfers - shell: "~/pg_cluster/install/bin/dtmbench {{connections}} -w {{item}} -s {{offset}} -d 100000 -r 1 -n 1000 -a 1000000" + shell: '~/pg_cluster/install/bin/dtmbench {{connections}} -w {{item}} -s {{offset}} -d 100000 -r 1 -n 1000 -a 1000000 | sed "s/^/`hostname`:/"' register: transfers_result environment: LD_LIBRARY_PATH: "/home/{{ansible_ssh_user}}/pg_cluster/install/lib" From 7f4dd6b76a61d1b47d2c8f8027646d236ed2ad02 Mon Sep 17 00:00:00 2001 From: Stas Kelvich Date: Wed, 11 Nov 2015 17:06:59 +0300 Subject: [PATCH 30/46] some tests params change --- tests/perf.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/perf.yml b/tests/perf.yml index eee5e2f..1200a0b 100644 --- a/tests/perf.yml +++ b/tests/perf.yml @@ -38,11 +38,11 @@ gather_facts: no tasks: - name: run transfers - shell: '~/pg_cluster/install/bin/dtmbench {{connections}} -w {{item}} -s {{offset}} -d 100000 -r 1 -n 1000 -a 1000000 | sed "s/^/`hostname`:/"' + shell: '~/pg_cluster/install/bin/dtmbench {{connections}} -w {{item}} -s {{offset}} -d 100000 -r 1 -n 1000 -a 2000000 | sed "s/^/`hostname`:/"' register: transfers_result environment: LD_LIBRARY_PATH: "/home/{{ansible_ssh_user}}/pg_cluster/install/lib" - with_sequence: start=100 end=200 stride=100 + with_sequence: start=100 end=200 stride=50 - local_action: shell echo "{{transfers_result.results | map(attribute='stdout') | join('\n')}}" >> perf.results From 88ea1e19cebdeef835bf2fb9aea81dddec915bb1 Mon Sep 17 00:00:00 2001 From: Stas Kelvich Date: Wed, 11 Nov 2015 20:16:25 +0300 Subject: [PATCH 31/46] increase open files; save intermediate bench results; force postgres stop --- tests/deploy/cluster.yml | 6 ++++++ tests/deploy/hosts.sample | 14 +++++++++++--- tests/deploy/roles/postgres/tasks/main.yml | 14 +++++++++++++- tests/perf.yml | 3 ++- 4 files changed, 32 insertions(+), 5 deletions(-) diff --git a/tests/deploy/cluster.yml b/tests/deploy/cluster.yml index 3397d66..c1e8745 100644 --- a/tests/deploy/cluster.yml +++ b/tests/deploy/cluster.yml @@ -49,6 +49,12 @@ - hosts: clients tasks: + - name: increase open files + shell: "echo '{{ansible_ssh_user}} soft nofile 65535' > /etc/security/limits.d/cluster.conf" + args: + creates: "/etc/security/limits.d/cluster.conf" + sudo: yes + - name: copy pg source copy: src=./{{item}} dest=~/{{item}} mode=0755 with_items: diff --git a/tests/deploy/hosts.sample b/tests/deploy/hosts.sample index 61a49c3..46a55c5 100644 --- a/tests/deploy/hosts.sample +++ b/tests/deploy/hosts.sample @@ -1,8 +1,16 @@ [clients] -client1 ansible_ssh_user=cluster offset=6001 +158.250.29.4 ansible_ssh_user=cluster offset=1 +158.250.29.7 ansible_ssh_user=cluster ansible_ssh_port=2299 offset=100001 [nodes] -nodes1 ansible_ssh_user=cluster offset=2001 +158.250.29.5 ansible_ssh_user=cluster +158.250.29.6 ansible_ssh_user=cluster +158.250.29.8 ansible_ssh_user=cluster +158.250.29.9 ansible_ssh_user=cluster +158.250.29.10 ansible_ssh_user=cluster [master] -master1 ansible_ssh_user=cluster offset=1 +158.250.29.10 ansible_ssh_user=cluster + +[local] +localhost diff --git a/tests/deploy/roles/postgres/tasks/main.yml b/tests/deploy/roles/postgres/tasks/main.yml index f3b5d3c..6a86773 100644 --- a/tests/deploy/roles/postgres/tasks/main.yml +++ b/tests/deploy/roles/postgres/tasks/main.yml @@ -34,6 +34,12 @@ shell: sysctl kernel.sem='1000 128000 128 512' sudo: yes +- name: increase open files + shell: "echo '{{ansible_ssh_user}} soft nofile 65535' > /etc/security/limits.d/cluster.conf" + args: + creates: "/etc/security/limits.d/cluster.conf" + sudo: yes + ############################################################################# - name: clone postgres sources @@ -73,8 +79,14 @@ - stat: path={{pg_datadir}}/postmaster.pid register: pg_pidfile +# - name: stop postgres if it was running +# command: "{{pg_dst}}/bin/pg_ctl stop -w -D {{pg_datadir}}" +# environment: +# LD_LIBRARY_PATH: "{{pg_dst}}/lib" +# when: pg_pidfile.stat.exists + - name: stop postgres if it was running - command: "{{pg_dst}}/bin/pg_ctl stop -w -D {{pg_datadir}}" + shell: "kill -9 `head -n 1 {{pg_datadir}}/postmaster.pid`" environment: LD_LIBRARY_PATH: "{{pg_dst}}/lib" when: pg_pidfile.stat.exists diff --git a/tests/perf.yml b/tests/perf.yml index 1200a0b..fabf97d 100644 --- a/tests/perf.yml +++ b/tests/perf.yml @@ -37,8 +37,9 @@ - hosts: clients gather_facts: no tasks: + - name: run transfers - shell: '~/pg_cluster/install/bin/dtmbench {{connections}} -w {{item}} -s {{offset}} -d 100000 -r 1 -n 1000 -a 2000000 | sed "s/^/`hostname`:/"' + shell: '~/pg_cluster/install/bin/dtmbench {{connections}} -w {{item}} -s {{offset}} -d 100000 -r 1 -n 1000 -a 2000000 | tee -a perf.results | sed "s/^/`hostname`:/"' register: transfers_result environment: LD_LIBRARY_PATH: "/home/{{ansible_ssh_user}}/pg_cluster/install/lib" From d364f40a734fe705b443f69f9ca821d62cf4557e Mon Sep 17 00:00:00 2001 From: Stas Kelvich Date: Wed, 11 Nov 2015 20:16:52 +0300 Subject: [PATCH 32/46] rm hosts --- tests/deploy/hosts | 16 ---------------- 1 file changed, 16 deletions(-) delete mode 100644 tests/deploy/hosts diff --git a/tests/deploy/hosts b/tests/deploy/hosts deleted file mode 100644 index a31b9db..0000000 --- a/tests/deploy/hosts +++ /dev/null @@ -1,16 +0,0 @@ -[clients] -158.250.29.4 ansible_ssh_user=cluster offset=600001 -158.250.29.7 ansible_ssh_user=cluster ansible_ssh_port=2299 offset=300001 - -[nodes] -158.250.29.5 ansible_ssh_user=cluster offset=500001 -158.250.29.6 ansible_ssh_user=cluster offset=400001 -158.250.29.8 ansible_ssh_user=cluster offset=200001 -158.250.29.9 ansible_ssh_user=cluster offset=100001 -158.250.29.10 ansible_ssh_user=cluster offset=1 - -[master] -158.250.29.10 ansible_ssh_user=cluster offset=1 - -[local] -localhost From 812cfb919abfa5e0a946ae14c1b8443ec8f0746a Mon Sep 17 00:00:00 2001 From: Stas Kelvich Date: Wed, 11 Nov 2015 20:20:39 +0300 Subject: [PATCH 33/46] bigger range of connections --- tests/perf.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/perf.yml b/tests/perf.yml index fabf97d..baab945 100644 --- a/tests/perf.yml +++ b/tests/perf.yml @@ -43,7 +43,7 @@ register: transfers_result environment: LD_LIBRARY_PATH: "/home/{{ansible_ssh_user}}/pg_cluster/install/lib" - with_sequence: start=100 end=200 stride=50 + with_sequence: start=100 end=400 stride=50 - local_action: shell echo "{{transfers_result.results | map(attribute='stdout') | join('\n')}}" >> perf.results From b652c1d1e3ac71d9c75c5d29c62a243c2c63f785 Mon Sep 17 00:00:00 2001 From: Stas Kelvich Date: Wed, 11 Nov 2015 21:00:50 +0300 Subject: [PATCH 34/46] do not loop transfers inside ansible role; better logging --- tests/perf.yml | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/tests/perf.yml b/tests/perf.yml index baab945..dd0d2f8 100644 --- a/tests/perf.yml +++ b/tests/perf.yml @@ -30,7 +30,7 @@ gather_facts: no tasks: - name: init database - shell: "~/pg_cluster/install/bin/dtmbench {{connections}} -a 1000000 -i" + shell: "~/pg_cluster/install/bin/dtmbench {{connections}} -a 2000000 -i" register: init_result - debug: var=init_result @@ -38,13 +38,21 @@ gather_facts: no tasks: + - local_action: shell echo "Bench started at `date`" >> perf.results + - name: run transfers - shell: '~/pg_cluster/install/bin/dtmbench {{connections}} -w {{item}} -s {{offset}} -d 100000 -r 1 -n 1000 -a 2000000 | tee -a perf.results | sed "s/^/`hostname`:/"' + shell: > + ~/pg_cluster/install/bin/dtmbench {{connections}} + -w {{conns | d(200)}} -s {{offset}} -d 100000 -r 1 -n 1000 -a 2000000 | + tee -a perf.results | + sed "s/^/`hostname`:/" register: transfers_result environment: LD_LIBRARY_PATH: "/home/{{ansible_ssh_user}}/pg_cluster/install/lib" - with_sequence: start=100 end=400 stride=50 - - local_action: shell echo "{{transfers_result.results | map(attribute='stdout') | join('\n')}}" >> perf.results + - debug: var=transfers_result + + - local_action: 'shell echo "{{transfers_result.stdout }}" >> perf.results' + + - local_action: shell echo "Bench finished at `date`" >> perf.results - - debug: msg="{{ transfers_result.results | map(attribute='stdout') | join('\n') }}" From 72e2fc38ef9087c0b3738cab298b6b87f0db7edc Mon Sep 17 00:00:00 2001 From: Stas Kelvich Date: Wed, 11 Nov 2015 21:14:19 +0300 Subject: [PATCH 35/46] max open files #2 --- tests/deploy/cluster.yml | 13 ++++++++----- tests/deploy/roles/postgres/tasks/main.yml | 14 +++++++++----- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/tests/deploy/cluster.yml b/tests/deploy/cluster.yml index c1e8745..770e2cd 100644 --- a/tests/deploy/cluster.yml +++ b/tests/deploy/cluster.yml @@ -46,13 +46,16 @@ environment: LD_LIBRARY_PATH: "{{pg_dst}}/lib/" - - hosts: clients tasks: - - name: increase open files - shell: "echo '{{ansible_ssh_user}} soft nofile 65535' > /etc/security/limits.d/cluster.conf" - args: - creates: "/etc/security/limits.d/cluster.conf" + - name: increase max open files + lineinfile: + dest: /etc/security/limits.d/cluster.conf + line: "{{item}}" + state: present + with_items: + - '{{ansible_ssh_user}} soft nofile 65535' + - '{{ansible_ssh_user}} hard nofile 65535' sudo: yes - name: copy pg source diff --git a/tests/deploy/roles/postgres/tasks/main.yml b/tests/deploy/roles/postgres/tasks/main.yml index 6a86773..ef3028d 100644 --- a/tests/deploy/roles/postgres/tasks/main.yml +++ b/tests/deploy/roles/postgres/tasks/main.yml @@ -10,7 +10,7 @@ - bison - flex - libreadline-dev - when: ansible_os_family == "Debian" + when: (pg_copydist is undefined) and ansible_os_family == "Debian" sudo: yes - name: ensure dependencies (RedHat) @@ -34,10 +34,14 @@ shell: sysctl kernel.sem='1000 128000 128 512' sudo: yes -- name: increase open files - shell: "echo '{{ansible_ssh_user}} soft nofile 65535' > /etc/security/limits.d/cluster.conf" - args: - creates: "/etc/security/limits.d/cluster.conf" +- name: increase max open files + lineinfile: + dest: /etc/security/limits.d/cluster.conf + line: "{{item}}" + state: present + with_items: + - '{{ansible_ssh_user}} soft nofile 65535' + - '{{ansible_ssh_user}} hard nofile 65535' sudo: yes ############################################################################# From bf4de8dc8eaaf4ce76a57bd5c57fbf3f8ff4aa63 Mon Sep 17 00:00:00 2001 From: Stas Kelvich Date: Wed, 11 Nov 2015 21:41:50 +0300 Subject: [PATCH 36/46] nconns now means number of node connections --- tests/perf.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/perf.yml b/tests/perf.yml index dd0d2f8..847b80d 100644 --- a/tests/perf.yml +++ b/tests/perf.yml @@ -43,7 +43,8 @@ - name: run transfers shell: > ~/pg_cluster/install/bin/dtmbench {{connections}} - -w {{conns | d(200)}} -s {{offset}} -d 100000 -r 1 -n 1000 -a 2000000 | + -w {{ (nconns | d(100)| int)*(nnodes | d(2) | int)/(2*( groups['clients'] | count))}} + -s {{offset}} -d 100000 -r 1 -n 1000 -a 2000000 | tee -a perf.results | sed "s/^/`hostname`:/" register: transfers_result From cbe347577ffb2dd099c33417bfac4ff49ab8f520 Mon Sep 17 00:00:00 2001 From: Stas Kelvich Date: Wed, 11 Nov 2015 21:55:45 +0300 Subject: [PATCH 37/46] create limits file --- tests/deploy/cluster.yml | 1 + tests/deploy/roles/postgres/tasks/main.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/tests/deploy/cluster.yml b/tests/deploy/cluster.yml index 770e2cd..e8d94cd 100644 --- a/tests/deploy/cluster.yml +++ b/tests/deploy/cluster.yml @@ -53,6 +53,7 @@ dest: /etc/security/limits.d/cluster.conf line: "{{item}}" state: present + create: true with_items: - '{{ansible_ssh_user}} soft nofile 65535' - '{{ansible_ssh_user}} hard nofile 65535' diff --git a/tests/deploy/roles/postgres/tasks/main.yml b/tests/deploy/roles/postgres/tasks/main.yml index ef3028d..44dbdf5 100644 --- a/tests/deploy/roles/postgres/tasks/main.yml +++ b/tests/deploy/roles/postgres/tasks/main.yml @@ -39,6 +39,7 @@ dest: /etc/security/limits.d/cluster.conf line: "{{item}}" state: present + create: true with_items: - '{{ansible_ssh_user}} soft nofile 65535' - '{{ansible_ssh_user}} hard nofile 65535' From 0510958cf24837fc2887068644d6646b39979f58 Mon Sep 17 00:00:00 2001 From: Dmitry Vasilyev Date: Wed, 11 Nov 2015 22:43:15 +0300 Subject: [PATCH 38/46] fix LD_LIBRARY_PATH --- tests/.gitignore | 3 +++ tests/deploy/cluster.yml | 2 +- tests/deploy/roles/postgres/tasks/main.yml | 6 +++--- tests/perf.yml | 4 +++- 4 files changed, 10 insertions(+), 5 deletions(-) create mode 100644 tests/.gitignore diff --git a/tests/.gitignore b/tests/.gitignore new file mode 100644 index 0000000..10ba26b --- /dev/null +++ b/tests/.gitignore @@ -0,0 +1,3 @@ +/deploy/hosts +/deploy/pg_cluster_install.tgz +/perf.results diff --git a/tests/deploy/cluster.yml b/tests/deploy/cluster.yml index e8d94cd..aa295c0 100644 --- a/tests/deploy/cluster.yml +++ b/tests/deploy/cluster.yml @@ -44,7 +44,7 @@ - name: restart postgrespro command: "{{pg_dst}}/bin/pg_ctl restart -w -D {{pg_datadir}} -l {{pg_datadir}}/pg.log" environment: - LD_LIBRARY_PATH: "{{pg_dst}}/lib/" + LD_LIBRARY_PATH: "$LD_LIBRARY_PATH:{{pg_dst}}/lib/" - hosts: clients tasks: diff --git a/tests/deploy/roles/postgres/tasks/main.yml b/tests/deploy/roles/postgres/tasks/main.yml index 44dbdf5..12aa2df 100644 --- a/tests/deploy/roles/postgres/tasks/main.yml +++ b/tests/deploy/roles/postgres/tasks/main.yml @@ -93,7 +93,7 @@ - name: stop postgres if it was running shell: "kill -9 `head -n 1 {{pg_datadir}}/postmaster.pid`" environment: - LD_LIBRARY_PATH: "{{pg_dst}}/lib" + LD_LIBRARY_PATH: "$LD_LIBRARY_PATH:{{pg_dst}}/lib" when: pg_pidfile.stat.exists - name: remove datadirs on datanodes @@ -103,7 +103,7 @@ - name: create datadirs on datanodes command: "{{pg_dst}}/bin/initdb {{pg_datadir}}" environment: - LD_LIBRARY_PATH: "{{pg_dst}}/lib/" + LD_LIBRARY_PATH: "$LD_LIBRARY_PATH:{{pg_dst}}/lib/" args: creates: "{{pg_datadir}}" @@ -129,5 +129,5 @@ - name: start postgrespro shell: "{{pg_dst}}/bin/pg_ctl start -w -D {{pg_datadir}} -l {{pg_datadir}}/pg.log" environment: - LD_LIBRARY_PATH: "{{pg_dst}}/lib/" + LD_LIBRARY_PATH: "$LD_LIBRARY_PATH:{{pg_dst}}/lib" diff --git a/tests/perf.yml b/tests/perf.yml index 847b80d..57109c0 100644 --- a/tests/perf.yml +++ b/tests/perf.yml @@ -30,6 +30,8 @@ gather_facts: no tasks: - name: init database + environment: + LD_LIBRARY_PATH: "$LD_LIBRARY_PATH:/home/{{ansible_ssh_user}}/pg_cluster/install/lib" shell: "~/pg_cluster/install/bin/dtmbench {{connections}} -a 2000000 -i" register: init_result - debug: var=init_result @@ -49,7 +51,7 @@ sed "s/^/`hostname`:/" register: transfers_result environment: - LD_LIBRARY_PATH: "/home/{{ansible_ssh_user}}/pg_cluster/install/lib" + LD_LIBRARY_PATH: "$LD_LIBRARY_PATH:/home/{{ansible_ssh_user}}/pg_cluster/install/lib" - debug: var=transfers_result From e2050fa468a3afd42a3e9ad4f927e63f5ca8c182 Mon Sep 17 00:00:00 2001 From: Konstantin Knizhnik Date: Fri, 13 Nov 2015 14:32:50 +0300 Subject: [PATCH 39/46] Imporove sleep statistic reporting --- pg_dtm.c | 15 +++++++++++---- tests/deploy/cluster.yml | 2 +- tests/run.sh | 3 +-- tests/transfers.go | 12 ++++++------ 4 files changed, 19 insertions(+), 13 deletions(-) diff --git a/pg_dtm.c b/pg_dtm.c index fd8a779..6fd9833 100644 --- a/pg_dtm.c +++ b/pg_dtm.c @@ -438,11 +438,21 @@ TransactionId DtmGetOldestXmin(Relation rel, bool ignoreVacuum) bool DtmXidInMVCCSnapshot(TransactionId xid, Snapshot snapshot) { +#if TRACE_SLEEP_TIME + static timestamp_t firstReportTime; + static timestamp_t prevReportTime; + static timestamp_t totalSleepTime; +#endif timestamp_t delay = MIN_WAIT_TIMEOUT; Assert(xid != InvalidTransactionId); SpinLockAcquire(&local->lock); +#if TRACE_SLEEP_TIME + if (firstReportTime == 0) { + firstReportTime = dtm_get_current_time(); + } +#endif while (true) { DtmTransStatus* ts = (DtmTransStatus*)hash_search(xid2status, &xid, HASH_FIND, NULL); @@ -461,14 +471,11 @@ bool DtmXidInMVCCSnapshot(TransactionId xid, Snapshot snapshot) #if TRACE_SLEEP_TIME { timestamp_t now = dtm_get_current_time(); - static timestamp_t firstReportTime; - static timestamp_t prevReportTime; - static timestamp_t totalSleepTime; #endif dtm_sleep(delay); #if TRACE_SLEEP_TIME totalSleepTime += dtm_get_current_time() - now; - if (now > prevReportTime + USEC*10) { + if (now > prevReportTime + USEC*1) { prevReportTime = now; if (firstReportTime == 0) { firstReportTime = now; diff --git a/tests/deploy/cluster.yml b/tests/deploy/cluster.yml index 6398609..088a766 100644 --- a/tests/deploy/cluster.yml +++ b/tests/deploy/cluster.yml @@ -11,7 +11,7 @@ pg_destroy_and_init: true pg_datadir: ./postgrespro-data pg_config_role: - - line: "dtm.vacuum_delay=60" + - line: "dtm.vacuum_delay=1000" tasks: diff --git a/tests/run.sh b/tests/run.sh index 6b9f342..7bd17c6 100755 --- a/tests/run.sh +++ b/tests/run.sh @@ -1,5 +1,4 @@ ./dtmbench \ -c "dbname=postgres host=localhost user=knizhnik port=5432 sslmode=disable" \ -c "dbname=postgres host=localhost user=knizhnik port=5433 sslmode=disable" \ --c "dbname=postgres host=localhost user=knizhnik port=5434 sslmode=disable" \ --n 1000 -a 1000 -w 10 -r 1 $* +-n 10000 -a 1000 -w 10 -r 1 $* diff --git a/tests/transfers.go b/tests/transfers.go index 514910d..efe7655 100644 --- a/tests/transfers.go +++ b/tests/transfers.go @@ -18,14 +18,14 @@ const ( var cfg1 = pgx.ConnConfig{ - Host: "astro9", - Port: 15432, + Host: "127.0.0.1", + Port: 5432, Database: "postgres", } var cfg2 = pgx.ConnConfig{ - Host: "astro9", - Port: 15433, + Host: "127.0.0.1", + Port: 5433, Database: "postgres", } @@ -109,8 +109,8 @@ func transfer(id int, wg *sync.WaitGroup) { gtid := strconv.Itoa(id) + "." + strconv.Itoa(i) amount := 2*rand.Intn(2) - 1 - account1 := 2*id+1 - account2 := 2*id+2 + account1 := rand.Intn(N_ACCOUNTS) + account2 := rand.Intn(N_ACCOUNTS) exec(conn1, "begin transaction") exec(conn2, "begin transaction") From fc142bad326aa35fcd8c8dc9f7794d10fa619021 Mon Sep 17 00:00:00 2001 From: knizhnik Date: Thu, 26 Nov 2015 23:36:30 +0300 Subject: [PATCH 40/46] Support subtransactions --- pg_dtm.c | 6 +++++- tests/dtmbench.cpp | 11 +++++++---- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/pg_dtm.c b/pg_dtm.c index 6fd9833..a2f241b 100644 --- a/pg_dtm.c +++ b/pg_dtm.c @@ -21,6 +21,7 @@ #include "access/xact.h" #include "access/xtm.h" #include "access/transam.h" +#include "access/subtrans.h" #include "access/xlog.h" #include "access/clog.h" #include "access/twophase.h" @@ -455,7 +456,10 @@ bool DtmXidInMVCCSnapshot(TransactionId xid, Snapshot snapshot) #endif while (true) { - DtmTransStatus* ts = (DtmTransStatus*)hash_search(xid2status, &xid, HASH_FIND, NULL); + DtmTransStatus* ts; + TransactionId subxid = xid; + while ((ts = (DtmTransStatus*)hash_search(xid2status, &subxid, HASH_FIND, NULL)) == NULL + && TransactionIdIsValid(subxid = SubTransGetParent(subxid))); if (ts != NULL) { if (ts->cid > dtm_tx.snapshot) { diff --git a/tests/dtmbench.cpp b/tests/dtmbench.cpp index ce3bcc5..2c89b72 100644 --- a/tests/dtmbench.cpp +++ b/tests/dtmbench.cpp @@ -68,7 +68,7 @@ struct config nWriters = 10; nIterations = 1000; nAccounts = 100000; - startId = 1; + startId = 0; diapason = 100000; } }; @@ -177,7 +177,10 @@ void* writer(void* arg) csn_t snapshot = execQuery(srcTx, "select dtm_extend('%s')", gtid); snapshot = execQuery(dstTx, "select dtm_access(%ld, '%s')", snapshot, gtid); - exec(srcTx, "update t set v = v - 1 where u=%d", srcAcc); + exec(srcTx, "savepoint c1"); + exec(dstTx, "savepoint c2"); + + exec(srcTx, "update t set v = v - 1 where u=%d", srcAcc); exec(dstTx, "update t set v = v + 1 where u=%d", dstAcc); exec(srcTx, "prepare transaction '%s'", gtid); @@ -260,7 +263,7 @@ int main (int argc, char* argv[]) return 1; } - if (cfg.startId + cfg.diapason - 1 > cfg.nAccounts) { + if (cfg.startId + cfg.diapason > cfg.nAccounts) { printf("startId + diapason should be less that nAccounts. Exiting.\n"); return 1; } @@ -305,7 +308,7 @@ int main (int argc, char* argv[]) printf( "{\"update_tps\":%f, \"read_tps\":%f," " \"readers\":%d, \"writers\":%d," - " \"accounts\":%d, \"iterations\":%d, \"hosts\":%d}\n", + " \"accounts\":%d, \"iterations\":%d, \"hosts\":%ld}\n", (double)(nWrites*USEC)/elapsed, (double)(nReads*USEC)/elapsed, cfg.nReaders, From d9e190eefc6fe5bc936acca76ca6f59b96cbdb51 Mon Sep 17 00:00:00 2001 From: Konstantin Knizhnik Date: Fri, 27 Nov 2015 13:19:19 +0300 Subject: [PATCH 41/46] Support subtransactions --- pg_dtm.c | 45 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 36 insertions(+), 9 deletions(-) diff --git a/pg_dtm.c b/pg_dtm.c index a2f241b..91dd1fe 100644 --- a/pg_dtm.c +++ b/pg_dtm.c @@ -83,8 +83,9 @@ static Snapshot DtmGetSnapshot(Snapshot snapshot); static TransactionId DtmGetOldestXmin(Relation rel, bool ignoreVacuum); static bool DtmXidInMVCCSnapshot(TransactionId xid, Snapshot snapshot); static TransactionId DtmAdjustOldestXid(TransactionId xid); +static void DtmSetTransactionStatus(TransactionId xid, int nsubxids, TransactionId *subxids, XidStatus status, XLogRecPtr lsn); -static TransactionManager DtmTM = { PgTransactionIdGetStatus, PgTransactionIdSetTreeStatus, DtmGetSnapshot, PgGetNewTransactionId, DtmGetOldestXmin, PgTransactionIdIsInProgress, PgGetGlobalTransactionId, DtmXidInMVCCSnapshot }; +static TransactionManager DtmTM = { PgTransactionIdGetStatus, DtmSetTransactionStatus, DtmGetSnapshot, PgGetNewTransactionId, DtmGetOldestXmin, PgTransactionIdIsInProgress, PgGetGlobalTransactionId, DtmXidInMVCCSnapshot }; void _PG_init(void); void _PG_fini(void); @@ -456,10 +457,11 @@ bool DtmXidInMVCCSnapshot(TransactionId xid, Snapshot snapshot) #endif while (true) { - DtmTransStatus* ts; - TransactionId subxid = xid; - while ((ts = (DtmTransStatus*)hash_search(xid2status, &subxid, HASH_FIND, NULL)) == NULL - && TransactionIdIsValid(subxid = SubTransGetParent(subxid))); + DtmTransStatus* ts = (DtmTransStatus*)hash_search(xid2status, &xid, HASH_FIND, NULL); + if (ts == NULL && TransactionIdFollowsOrEquals(xid, TransactionXmin)) { + xid = SubTransGetTopmostTransaction(xid); + ts = (DtmTransStatus*)hash_search(xid2status, &xid, HASH_FIND, NULL); + } if (ts != NULL) { if (ts->cid > dtm_tx.snapshot) { @@ -679,8 +681,8 @@ void DtmLocalCommit(DtmTransState* x) if (x->is_prepared) { Assert(found); Assert(x->is_global); - } else { - Assert(!found); + } else if (!found) { + //Assert(!found); ts->cid = dtm_get_cid(); IncludeInTransactionList(ts); } @@ -718,8 +720,8 @@ void DtmLocalAbort(DtmTransState* x) if (x->is_prepared) { Assert(found); Assert(x->is_global); - } else { - Assert(!found); + } else if (!found) { + //Assert(!found); ts->cid = dtm_get_cid(); IncludeInTransactionList(ts); } @@ -738,3 +740,28 @@ void DtmLocalEnd(DtmTransState* x) x->cid = INVALID_CID; } +void DtmSetTransactionStatus(TransactionId xid, int nsubxids, TransactionId *subxids, XidStatus status, XLogRecPtr lsn) +{ + if (nsubxids != 0) { + SpinLockAcquire(&local->lock); + { + int i; + bool found; + DtmTransStatus* ts = (DtmTransStatus*)hash_search(xid2status, &xid, HASH_ENTER, &found); + if (!found) { + ts->cid = dtm_get_cid(); + } + ts->status = status; + for (i = 0; i < nsubxids; i++) { + DtmTransStatus* sts = (DtmTransStatus*)hash_search(xid2status, &subxids[i], HASH_ENTER, &found); + Assert(!found); + sts->status = status; + sts->cid = ts->cid; + sts->next = ts->next; + ts->next = sts; + } + } + SpinLockRelease(&local->lock); + } + PgTransactionIdSetTreeStatus(xid, nsubxids, subxids, status, lsn); +} From 7841007581fb7647ed666694094436777652327b Mon Sep 17 00:00:00 2001 From: Konstantin Knizhnik Date: Fri, 27 Nov 2015 19:42:56 +0300 Subject: [PATCH 42/46] Support subtransactions --- pg_dtm.c | 9 ++++++++- tests/dtmbench.cpp | 25 ++++++++++++++++++++----- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/pg_dtm.c b/pg_dtm.c index 91dd1fe..831e8a2 100644 --- a/pg_dtm.c +++ b/pg_dtm.c @@ -84,8 +84,9 @@ static TransactionId DtmGetOldestXmin(Relation rel, bool ignoreVacuum); static bool DtmXidInMVCCSnapshot(TransactionId xid, Snapshot snapshot); static TransactionId DtmAdjustOldestXid(TransactionId xid); static void DtmSetTransactionStatus(TransactionId xid, int nsubxids, TransactionId *subxids, XidStatus status, XLogRecPtr lsn); +static bool DtmDetectGlobalDeadLock(PGPROC* proc); -static TransactionManager DtmTM = { PgTransactionIdGetStatus, DtmSetTransactionStatus, DtmGetSnapshot, PgGetNewTransactionId, DtmGetOldestXmin, PgTransactionIdIsInProgress, PgGetGlobalTransactionId, DtmXidInMVCCSnapshot }; +static TransactionManager DtmTM = { PgTransactionIdGetStatus, DtmSetTransactionStatus, DtmGetSnapshot, PgGetNewTransactionId, DtmGetOldestXmin, PgTransactionIdIsInProgress, PgGetGlobalTransactionId, DtmXidInMVCCSnapshot, DtmDetectGlobalDeadLock }; void _PG_init(void); void _PG_fini(void); @@ -765,3 +766,9 @@ void DtmSetTransactionStatus(TransactionId xid, int nsubxids, TransactionId *sub } PgTransactionIdSetTreeStatus(xid, nsubxids, subxids, status, lsn); } + +bool DtmDetectGlobalDeadLock(PGPROC* proc) +{ + elog(WARNING, "Global deadlock?"); + return true; +} diff --git a/tests/dtmbench.cpp b/tests/dtmbench.cpp index 2c89b72..28cbf05 100644 --- a/tests/dtmbench.cpp +++ b/tests/dtmbench.cpp @@ -40,11 +40,13 @@ struct thread { pthread_t t; size_t proceeded; + size_t aborts; int id; void start(int tid, thread_proc_t proc) { id = tid; proceeded = 0; + aborts = 0; pthread_create(&t, NULL, proc, this); } @@ -160,12 +162,13 @@ void* writer(void* arg) int srcAcc = cfg.startId + random() % cfg.diapason; int dstAcc = cfg.startId + random() % cfg.diapason; + #if 1 // avoid deadlocks if (srcAcc > dstAcc) { int tmpAcc = dstAcc; dstAcc = srcAcc; srcAcc = tmpAcc; } - + #endif sprintf(gtid, "%d.%d.%d", cfg.startId, t.id, i); nontransaction srcTx(*srcCon); @@ -180,8 +183,16 @@ void* writer(void* arg) exec(srcTx, "savepoint c1"); exec(dstTx, "savepoint c2"); - exec(srcTx, "update t set v = v - 1 where u=%d", srcAcc); - exec(dstTx, "update t set v = v + 1 where u=%d", dstAcc); + try { + exec(srcTx, "update t set v = v - 1 where u=%d", srcAcc); + exec(dstTx, "update t set v = v + 1 where u=%d", dstAcc); + } catch (pqxx_exception const& x) { + exec(srcTx, "rollback"); + exec(dstTx, "rollback"); + t.aborts += 1; + i -= 1; + continue; + } exec(srcTx, "prepare transaction '%s'", gtid); exec(dstTx, "prepare transaction '%s'", gtid); @@ -281,7 +292,8 @@ int main (int argc, char* argv[]) vector writers(cfg.nWriters); size_t nReads = 0; size_t nWrites = 0; - + size_t nAborts = 0; + for (int i = 0; i < cfg.nReaders; i++) { readers[i].start(i, reader); } @@ -292,6 +304,7 @@ int main (int argc, char* argv[]) for (int i = 0; i < cfg.nWriters; i++) { writers[i].wait(); nWrites += writers[i].proceeded; + nAborts += writers[i].aborts; } running = false; @@ -307,12 +320,14 @@ int main (int argc, char* argv[]) printf( "{\"update_tps\":%f, \"read_tps\":%f," - " \"readers\":%d, \"writers\":%d," + " \"readers\":%d, \"writers\":%d, \"aborts\":%ld, \"abort_percent\": %d," " \"accounts\":%d, \"iterations\":%d, \"hosts\":%ld}\n", (double)(nWrites*USEC)/elapsed, (double)(nReads*USEC)/elapsed, cfg.nReaders, cfg.nWriters, + nAborts, + (int)(nAborts*100/nWrites), cfg.nAccounts, cfg.nIterations, cfg.connections.size() From 610f7c57d4cd12faaa20c4f30150fe7d9017367a Mon Sep 17 00:00:00 2001 From: knizhnik Date: Sun, 29 Nov 2015 22:08:11 +0300 Subject: [PATCH 43/46] Fix handlings of subtransactions --- pg_dtm--1.0.sql | 4 ++ pg_dtm.c | 54 +++++++++++++++++----- tests/dtmbench.cpp | 110 ++++++++++++++++++++++++++++++++++----------- tests/makefile | 2 +- 4 files changed, 132 insertions(+), 38 deletions(-) diff --git a/pg_dtm--1.0.sql b/pg_dtm--1.0.sql index 1e6766f..dcd81ac 100644 --- a/pg_dtm--1.0.sql +++ b/pg_dtm--1.0.sql @@ -20,3 +20,7 @@ LANGUAGE C; CREATE FUNCTION dtm_end_prepare(gtid cstring, csn bigint) RETURNS void AS 'MODULE_PATHNAME','dtm_end_prepare' LANGUAGE C; + +CREATE FUNCTION dtm_get_csn(xid integer) RETURNS bigint +AS 'MODULE_PATHNAME','dtm_get_csn' +LANGUAGE C; diff --git a/pg_dtm.c b/pg_dtm.c index 831e8a2..7f10ba8 100644 --- a/pg_dtm.c +++ b/pg_dtm.c @@ -85,6 +85,7 @@ static bool DtmXidInMVCCSnapshot(TransactionId xid, Snapshot snapshot); static TransactionId DtmAdjustOldestXid(TransactionId xid); static void DtmSetTransactionStatus(TransactionId xid, int nsubxids, TransactionId *subxids, XidStatus status, XLogRecPtr lsn); static bool DtmDetectGlobalDeadLock(PGPROC* proc); +static cid_t DtmGetCsn(TransactionId xid); static TransactionManager DtmTM = { PgTransactionIdGetStatus, DtmSetTransactionStatus, DtmGetSnapshot, PgGetNewTransactionId, DtmGetOldestXmin, PgTransactionIdIsInProgress, PgGetGlobalTransactionId, DtmXidInMVCCSnapshot, DtmDetectGlobalDeadLock }; @@ -308,6 +309,7 @@ PG_FUNCTION_INFO_V1(dtm_access); PG_FUNCTION_INFO_V1(dtm_begin_prepare); PG_FUNCTION_INFO_V1(dtm_prepare); PG_FUNCTION_INFO_V1(dtm_end_prepare); +PG_FUNCTION_INFO_V1(dtm_get_csn); Datum dtm_extend(PG_FUNCTION_ARGS) @@ -357,7 +359,13 @@ dtm_end_prepare(PG_FUNCTION_ARGS) PG_RETURN_VOID(); } - +Datum +dtm_get_csn(PG_FUNCTION_ARGS) +{ + TransactionId xid = PG_GETARG_INT32(0); + cid_t csn = DtmGetCsn(xid); + PG_RETURN_INT64(csn); +} /* * *************************************************************************** */ @@ -392,13 +400,22 @@ static int dtm_gtid_match_fn(const void *key1, const void *key2, Size keysize) return strcmp((GlobalTransactionId)key1, (GlobalTransactionId)key2); } -static void IncludeInTransactionList(DtmTransStatus* ts) +static void DtmTransactionListAppend(DtmTransStatus* ts) { ts->next = NULL; *local->trans_list_tail = ts; local->trans_list_tail = &ts->next; } +static void DtmTransactionListInsertAfter(DtmTransStatus* after, DtmTransStatus* ts) +{ + ts->next = after->next; + after->next = ts; + if (local->trans_list_tail == &after->next) { + local->trans_list_tail = &ts->next; + } +} + static TransactionId DtmAdjustOldestXid(TransactionId xid) { if (TransactionIdIsValid(xid)) { @@ -459,9 +476,12 @@ bool DtmXidInMVCCSnapshot(TransactionId xid, Snapshot snapshot) while (true) { DtmTransStatus* ts = (DtmTransStatus*)hash_search(xid2status, &xid, HASH_FIND, NULL); - if (ts == NULL && TransactionIdFollowsOrEquals(xid, TransactionXmin)) { - xid = SubTransGetTopmostTransaction(xid); - ts = (DtmTransStatus*)hash_search(xid2status, &xid, HASH_FIND, NULL); + if (ts == NULL && + !(TransactionIdFollowsOrEquals(xid, snapshot->xmax) || TransactionIdPrecedes(xid, snapshot->xmin))) + { + //TransactionIdFollowsOrEquals(xid, TransactionXmin)) { + TransactionId subxid = SubTransGetTopmostTransaction(xid); + ts = (DtmTransStatus*)hash_search(xid2status, &subxid, HASH_FIND, NULL); } if (ts != NULL) { @@ -618,7 +638,7 @@ void DtmLocalBeginPrepare(GlobalTransactionId gtid) ts = (DtmTransStatus*)hash_search(xid2status, &id->xid, HASH_ENTER, NULL); ts->status = TRANSACTION_STATUS_IN_PROGRESS; ts->cid = dtm_get_cid(); - IncludeInTransactionList(ts); + DtmTransactionListAppend(ts); } SpinLockRelease(&local->lock); } @@ -685,7 +705,7 @@ void DtmLocalCommit(DtmTransState* x) } else if (!found) { //Assert(!found); ts->cid = dtm_get_cid(); - IncludeInTransactionList(ts); + DtmTransactionListAppend(ts); } x->cid = ts->cid; ts->status = TRANSACTION_STATUS_COMMITTED; @@ -724,7 +744,7 @@ void DtmLocalAbort(DtmTransState* x) } else if (!found) { //Assert(!found); ts->cid = dtm_get_cid(); - IncludeInTransactionList(ts); + DtmTransactionListAppend(ts); } x->cid = ts->cid; ts->status = TRANSACTION_STATUS_ABORTED; @@ -758,8 +778,7 @@ void DtmSetTransactionStatus(TransactionId xid, int nsubxids, TransactionId *sub Assert(!found); sts->status = status; sts->cid = ts->cid; - sts->next = ts->next; - ts->next = sts; + DtmTransactionListInsertAfter(ts, sts); } } SpinLockRelease(&local->lock); @@ -772,3 +791,18 @@ bool DtmDetectGlobalDeadLock(PGPROC* proc) elog(WARNING, "Global deadlock?"); return true; } + +static cid_t DtmGetCsn(TransactionId xid) +{ + cid_t csn = 0; + SpinLockAcquire(&local->lock); + { + DtmTransStatus* ts = (DtmTransStatus*)hash_search(xid2status, &xid, HASH_FIND, NULL); + if (ts != NULL) { + csn = ts->cid; + } + } + SpinLockRelease(&local->lock); + return csn; +} + diff --git a/tests/dtmbench.cpp b/tests/dtmbench.cpp index 28cbf05..c4570d2 100644 --- a/tests/dtmbench.cpp +++ b/tests/dtmbench.cpp @@ -41,12 +41,14 @@ struct thread pthread_t t; size_t proceeded; size_t aborts; + time_t max_trans_duration; int id; void start(int tid, thread_proc_t proc) { id = tid; proceeded = 0; aborts = 0; + max_trans_duration = 0; pthread_create(&t, NULL, proc, this); } @@ -63,6 +65,9 @@ struct config int nAccounts; int startId; int diapason; + bool deadlockFree; + bool maxSnapshot; + bool makeSavepoints; vector connections; config() { @@ -72,6 +77,8 @@ struct config nAccounts = 100000; startId = 0; diapason = 100000; + deadlockFree = false; + makeSavepoints = false; } }; @@ -87,6 +94,9 @@ static time_t getCurrentTime() return (time_t)tv.tv_sec*USEC + tv.tv_usec; } +inline csn_t max(csn_t t1, csn_t t2) { + return t1 < t2 ? t2 : t1; +} void exec(transaction_base& txn, char const* sql, ...) { @@ -119,16 +129,26 @@ void* reader(void* arg) int64_t prevSum = 0; while (running) { - csn_t snapshot; + csn_t snapshot = 0; vector< unique_ptr > txns(conns.size()); + time_t start = getCurrentTime(); for (size_t i = 0; i < conns.size(); i++) { txns[i] = new work(*conns[i]); } - for (size_t i = 0; i < txns.size(); i++) { - if (i == 0) { - snapshot = execQuery(*txns[i], "select dtm_extend()"); - } else { - snapshot = execQuery(*txns[i], "select dtm_access(%ld)", snapshot); + if (cfg.maxSnapshot) { + for (size_t i = 0; i < txns.size(); i++) { + snapshot = max(snapshot, execQuery(*txns[i], "select dtm_extend()")); + } + for (size_t i = 0; i < txns.size(); i++) { + execQuery(*txns[i], "select dtm_access(%ld)", snapshot); + } + } else { + for (size_t i = 0; i < txns.size(); i++) { + if (i == 0) { + snapshot = execQuery(*txns[i], "select dtm_extend()"); + } else { + snapshot = execQuery(*txns[i], "select dtm_access(%ld)", snapshot); + } } } int64_t sum = 0; @@ -136,10 +156,14 @@ void* reader(void* arg) sum += execQuery(*txns[i], "select sum(v) from t"); } if (sum != prevSum) { - printf("Total=%ld snapshot=%ld\n", sum, snapshot); + printf("Total=%ld snapshot=%ldm delta=%ld usec\n", sum, snapshot, getCurrentTime()-snapshot); prevSum = sum; } t.proceeded += 1; + time_t elapsed = getCurrentTime() - start; + if (elapsed > t.max_trans_duration) { + t.max_trans_duration = elapsed; + } } return NULL; } @@ -156,33 +180,37 @@ void* writer(void* arg) { char gtid[32]; - // int srcAcc = (random() % ((cfg.nAccounts-cfg.nWriters)/cfg.nWriters))*cfg.nWriters + t.id; - // int dstAcc = (random() % ((cfg.nAccounts-cfg.nWriters)/cfg.nWriters))*cfg.nWriters + t.id; - int srcAcc = cfg.startId + random() % cfg.diapason; int dstAcc = cfg.startId + random() % cfg.diapason; - #if 1 // avoid deadlocks - if (srcAcc > dstAcc) { + if (cfg.deadlockFree && srcAcc > dstAcc) { // avoid deadlocks int tmpAcc = dstAcc; dstAcc = srcAcc; srcAcc = tmpAcc; } - #endif sprintf(gtid, "%d.%d.%d", cfg.startId, t.id, i); nontransaction srcTx(*srcCon); nontransaction dstTx(*dstCon); + time_t start = getCurrentTime(); + exec(srcTx, "begin transaction"); exec(dstTx, "begin transaction"); - csn_t snapshot = execQuery(srcTx, "select dtm_extend('%s')", gtid); - snapshot = execQuery(dstTx, "select dtm_access(%ld, '%s')", snapshot, gtid); - - exec(srcTx, "savepoint c1"); - exec(dstTx, "savepoint c2"); - + if (cfg.maxSnapshot) { + csn_t snapshot = execQuery(srcTx, "select dtm_extend('%s')", gtid); + snapshot = max(snapshot, execQuery(dstTx, "select dtm_extend('%s')", gtid)); + execQuery(srcTx, "select dtm_access(%ld, '%s')", snapshot, gtid); + execQuery(dstTx, "select dtm_access(%ld, '%s')", snapshot, gtid); + } else { + csn_t snapshot = execQuery(srcTx, "select dtm_extend('%s')", gtid); + snapshot = execQuery(dstTx, "select dtm_access(%ld, '%s')", snapshot, gtid); + } + if (cfg.makeSavepoints) { + exec(srcTx, "savepoint c1"); + exec(dstTx, "savepoint c2"); + } try { exec(srcTx, "update t set v = v - 1 where u=%d", srcAcc); exec(dstTx, "update t set v = v + 1 where u=%d", dstAcc); @@ -204,7 +232,12 @@ void* writer(void* arg) exec(dstTx, "select dtm_end_prepare('%s', %ld)", gtid, csn); exec(srcTx, "commit prepared '%s'", gtid); exec(dstTx, "commit prepared '%s'", gtid); - + + time_t elapsed = getCurrentTime() - start; + if (elapsed > t.max_trans_duration) { + t.max_trans_duration = elapsed; + } + t.proceeded += 1; } return NULL; @@ -219,7 +252,7 @@ void initializeDatabase() exec(txn, "create extension pg_dtm"); exec(txn, "drop table if exists t"); exec(txn, "create table t(u int primary key, v int)"); - exec(txn, "insert into t (select generate_series(0,%d), %d)", cfg.nAccounts, 0); + exec(txn, "insert into t (select generate_series(0,%d), %d)", cfg.nAccounts-1, 0); txn.commit(); } } @@ -255,8 +288,18 @@ int main (int argc, char* argv[]) cfg.diapason = atoi(argv[++i]); continue; case 'C': + case 'c': cfg.connections.push_back(string(argv[++i])); continue; + case 'f': + cfg.deadlockFree = true; + continue; + case 'm': + cfg.maxSnapshot = true; + continue; + case 'x': + cfg.makeSavepoints = true; + continue; case 'i': initialize = true; continue; @@ -266,16 +309,19 @@ int main (int argc, char* argv[]) "\t-r N\tnumber of readers (1)\n" "\t-w N\tnumber of writers (10)\n" "\t-a N\tnumber of accounts (100000)\n" - "\t-s N\tperform updates starting from this id (1)\n" - "\t-d N\tperform updates in this diapason (100000)\n" + "\t-s N\tperform updates starting from this id (0)\n" + "\t-d N\tperform updates in this diapason (#accounts)\n" "\t-n N\tnumber of iterations (1000)\n" - "\t-C STR\tdatabase connection string\n" + "\t-c STR\tdatabase connection string\n" + "\t-f\tavoid deadlocks by ordering accounts\n" + "\t-m\tchoose maximal snapshot\n" + "\t-x\tmake savepoints\n" "\t-i\tinitialize datanase\n"); return 1; } if (cfg.startId + cfg.diapason > cfg.nAccounts) { - printf("startId + diapason should be less that nAccounts. Exiting.\n"); + cfg.diapason = cfg.nAccounts - cfg.startId; return 1; } @@ -293,7 +339,9 @@ int main (int argc, char* argv[]) size_t nReads = 0; size_t nWrites = 0; size_t nAborts = 0; - + time_t maxReadDuration = 0; + time_t maxWriteDuration = 0; + for (int i = 0; i < cfg.nReaders; i++) { readers[i].start(i, reader); } @@ -305,6 +353,9 @@ int main (int argc, char* argv[]) writers[i].wait(); nWrites += writers[i].proceeded; nAborts += writers[i].aborts; + if (writers[i].max_trans_duration > maxWriteDuration) { + maxWriteDuration = writers[i].max_trans_duration; + } } running = false; @@ -312,7 +363,10 @@ int main (int argc, char* argv[]) for (int i = 0; i < cfg.nReaders; i++) { readers[i].wait(); nReads += readers[i].proceeded; - } + if (readers[i].max_trans_duration > maxReadDuration) { + maxReadDuration = readers[i].max_trans_duration; + } + } time_t elapsed = getCurrentTime() - start; @@ -321,6 +375,7 @@ int main (int argc, char* argv[]) printf( "{\"update_tps\":%f, \"read_tps\":%f," " \"readers\":%d, \"writers\":%d, \"aborts\":%ld, \"abort_percent\": %d," + " \"max_read_duration\":%ld, \"max_write_duration\":%ld," " \"accounts\":%d, \"iterations\":%d, \"hosts\":%ld}\n", (double)(nWrites*USEC)/elapsed, (double)(nReads*USEC)/elapsed, @@ -328,6 +383,7 @@ int main (int argc, char* argv[]) cfg.nWriters, nAborts, (int)(nAborts*100/nWrites), + maxReadDuration, maxWriteDuration, cfg.nAccounts, cfg.nIterations, cfg.connections.size() diff --git a/tests/makefile b/tests/makefile index bcd7ee6..5246334 100644 --- a/tests/makefile +++ b/tests/makefile @@ -1,5 +1,5 @@ CXX=g++ -CXXFLAGS=-g -Wall -O2 -pthread +CXXFLAGS=-g -Wall -O0 -pthread all: dtmbench From c7ed87efab814ec4a0680fb6c0f70367237d3551 Mon Sep 17 00:00:00 2001 From: Konstantin Knizhnik Date: Mon, 30 Nov 2015 15:26:21 +0300 Subject: [PATCH 44/46] Rewrite support if subtransactions --- pg_dtm.c | 146 +++++++++++++++++++++++++++++++++---------------------- pg_dtm.h | 20 ++++---- 2 files changed, 100 insertions(+), 66 deletions(-) diff --git a/pg_dtm.c b/pg_dtm.c index 7f10ba8..8441a49 100644 --- a/pg_dtm.c +++ b/pg_dtm.c @@ -48,6 +48,7 @@ typedef struct DtmTransStatus { TransactionId xid; XidStatus status; + int nSubxids; cid_t cid; struct DtmTransStatus* next; } DtmTransStatus; @@ -65,6 +66,8 @@ typedef struct { char gtid[MAX_GTID_SIZE]; TransactionId xid; + TransactionId* subxids; + int nSubxids; } DtmTransId; @@ -75,7 +78,7 @@ static shmem_startup_hook_type prev_shmem_startup_hook; static HTAB* xid2status; static HTAB* gtid2xid; static DtmNodeState* local; -static DtmTransState dtm_tx; +static DtmCurrentTrans dtm_tx; static uint64 totalSleepInterrupts; static int DtmVacuumDelay; @@ -83,11 +86,11 @@ static Snapshot DtmGetSnapshot(Snapshot snapshot); static TransactionId DtmGetOldestXmin(Relation rel, bool ignoreVacuum); static bool DtmXidInMVCCSnapshot(TransactionId xid, Snapshot snapshot); static TransactionId DtmAdjustOldestXid(TransactionId xid); -static void DtmSetTransactionStatus(TransactionId xid, int nsubxids, TransactionId *subxids, XidStatus status, XLogRecPtr lsn); static bool DtmDetectGlobalDeadLock(PGPROC* proc); static cid_t DtmGetCsn(TransactionId xid); +static void DtmAddSubtransactions(DtmTransStatus* ts, TransactionId* subxids, int nSubxids); -static TransactionManager DtmTM = { PgTransactionIdGetStatus, DtmSetTransactionStatus, DtmGetSnapshot, PgGetNewTransactionId, DtmGetOldestXmin, PgTransactionIdIsInProgress, PgGetGlobalTransactionId, DtmXidInMVCCSnapshot, DtmDetectGlobalDeadLock }; +static TransactionManager DtmTM = { PgTransactionIdGetStatus, PgTransactionIdSetTreeStatus, DtmGetSnapshot, PgGetNewTransactionId, DtmGetOldestXmin, PgTransactionIdIsInProgress, PgGetGlobalTransactionId, DtmXidInMVCCSnapshot, DtmDetectGlobalDeadLock }; void _PG_init(void); void _PG_fini(void); @@ -290,6 +293,7 @@ dtm_xact_callback(XactEvent event, void *arg) break; case XACT_EVENT_PREPARE: + DtmLocalSavePreparedState(dtm_get_global_trans_id()); DtmLocalEnd(&dtm_tx); break; @@ -462,6 +466,7 @@ bool DtmXidInMVCCSnapshot(TransactionId xid, Snapshot snapshot) static timestamp_t firstReportTime; static timestamp_t prevReportTime; static timestamp_t totalSleepTime; + static timestamp_t maxSleepTime; #endif timestamp_t delay = MIN_WAIT_TIMEOUT; Assert(xid != InvalidTransactionId); @@ -476,13 +481,6 @@ bool DtmXidInMVCCSnapshot(TransactionId xid, Snapshot snapshot) while (true) { DtmTransStatus* ts = (DtmTransStatus*)hash_search(xid2status, &xid, HASH_FIND, NULL); - if (ts == NULL && - !(TransactionIdFollowsOrEquals(xid, snapshot->xmax) || TransactionIdPrecedes(xid, snapshot->xmin))) - { - //TransactionIdFollowsOrEquals(xid, TransactionXmin)) { - TransactionId subxid = SubTransGetTopmostTransaction(xid); - ts = (DtmTransStatus*)hash_search(xid2status, &subxid, HASH_FIND, NULL); - } if (ts != NULL) { if (ts->cid > dtm_tx.snapshot) { @@ -497,17 +495,21 @@ bool DtmXidInMVCCSnapshot(TransactionId xid, Snapshot snapshot) SpinLockRelease(&local->lock); #if TRACE_SLEEP_TIME { - timestamp_t now = dtm_get_current_time(); + timestamp_t delta, now = dtm_get_current_time(); #endif dtm_sleep(delay); #if TRACE_SLEEP_TIME - totalSleepTime += dtm_get_current_time() - now; - if (now > prevReportTime + USEC*1) { + delta = dtm_get_current_time() - now; + totalSleepTime += delta; + if (delta > maxSleepTime) { + maxSleepTime = delta; + } + if (now > prevReportTime + USEC*10) { prevReportTime = now; if (firstReportTime == 0) { firstReportTime = now; } else { - fprintf(stderr, "Snapshot sleep %lu of %lu usec (%f%%)\n", totalSleepTime, now - firstReportTime, totalSleepTime*100.0/(now - firstReportTime)); + fprintf(stderr, "Snapshot sleep %lu of %lu usec (%f%%), maximum=%lu\n", totalSleepTime, now - firstReportTime, totalSleepTime*100.0/(now - firstReportTime), maxSleepTime); } } } @@ -577,7 +579,7 @@ void DtmInitialize() } -void DtmLocalBegin(DtmTransState* x) +void DtmLocalBegin(DtmCurrentTrans* x) { if (x->xid == InvalidTransactionId) { SpinLockAcquire(&local->lock); @@ -592,23 +594,23 @@ void DtmLocalBegin(DtmTransState* x) } } -cid_t DtmLocalExtend(DtmTransState* x, GlobalTransactionId gtid) +cid_t DtmLocalExtend(DtmCurrentTrans* x, GlobalTransactionId gtid) { if (gtid != NULL) { SpinLockAcquire(&local->lock); { DtmTransId* id = (DtmTransId*)hash_search(gtid2xid, gtid, HASH_ENTER, NULL); - x->is_global = true; id->xid = x->xid; + id->nSubxids = 0; + id->subxids = 0; } SpinLockRelease(&local->lock); - } else { - x->is_global = true; - } + } + x->is_global = true; return x->snapshot; } -cid_t DtmLocalAccess(DtmTransState* x, GlobalTransactionId gtid, cid_t global_cid) +cid_t DtmLocalAccess(DtmCurrentTrans* x, GlobalTransactionId gtid, cid_t global_cid) { cid_t local_cid; SpinLockAcquire(&local->lock); @@ -616,6 +618,8 @@ cid_t DtmLocalAccess(DtmTransState* x, GlobalTransactionId gtid, cid_t global_ci if (gtid != NULL) { DtmTransId* id = (DtmTransId*)hash_search(gtid2xid, gtid, HASH_ENTER, NULL); id->xid = x->xid; + id->nSubxids = 0; + id->subxids = 0; } local_cid = dtm_sync(global_cid); x->snapshot = local_cid; @@ -638,7 +642,9 @@ void DtmLocalBeginPrepare(GlobalTransactionId gtid) ts = (DtmTransStatus*)hash_search(xid2status, &id->xid, HASH_ENTER, NULL); ts->status = TRANSACTION_STATUS_IN_PROGRESS; ts->cid = dtm_get_cid(); + ts->nSubxids = id->nSubxids; DtmTransactionListAppend(ts); + DtmAddSubtransactions(ts, id->subxids, id->nSubxids); } SpinLockRelease(&local->lock); } @@ -661,6 +667,7 @@ void DtmLocalEndPrepare(GlobalTransactionId gtid, cid_t cid) { DtmTransStatus* ts; DtmTransId* id; + int i; id = (DtmTransId*)hash_search(gtid2xid, gtid, HASH_FIND, NULL); Assert(id != NULL); @@ -668,7 +675,10 @@ void DtmLocalEndPrepare(GlobalTransactionId gtid, cid_t cid) ts = (DtmTransStatus*)hash_search(xid2status, &id->xid, HASH_FIND, NULL); Assert(ts != NULL); ts->cid = cid; - + for (i = 0; i < ts->nSubxids; i++) { + ts = ts->next; + ts->cid = cid; + } dtm_sync(cid); DTM_TRACE((stderr, "Prepare transaction %u(%s) with CSN %lu\n", id->xid, gtid, cid)); @@ -676,7 +686,7 @@ void DtmLocalEndPrepare(GlobalTransactionId gtid, cid_t cid) SpinLockRelease(&local->lock); } -void DtmLocalCommitPrepared(DtmTransState* x, GlobalTransactionId gtid) +void DtmLocalCommitPrepared(DtmCurrentTrans* x, GlobalTransactionId gtid) { Assert(gtid != NULL); @@ -688,33 +698,45 @@ void DtmLocalCommitPrepared(DtmTransState* x, GlobalTransactionId gtid) x->is_global = true; x->is_prepared = true; x->xid = id->xid; + free(id->subxids); + DTM_TRACE((stderr, "Global transaction %u(%s) is precommitted\n", x->xid, gtid)); } SpinLockRelease(&local->lock); } -void DtmLocalCommit(DtmTransState* x) +void DtmLocalCommit(DtmCurrentTrans* x) { SpinLockAcquire(&local->lock); { bool found; DtmTransStatus* ts = (DtmTransStatus*)hash_search(xid2status, &x->xid, HASH_ENTER, &found); + ts->status = TRANSACTION_STATUS_COMMITTED; if (x->is_prepared) { + int i; + DtmTransStatus* sts = ts; Assert(found); Assert(x->is_global); - } else if (!found) { - //Assert(!found); + for (i = 0; i < ts->nSubxids; i++) { + sts = sts->next; + Assert(sts->cid == ts->cid); + sts->status = TRANSACTION_STATUS_COMMITTED; + } + } else { + TransactionId* subxids; + Assert(!found); ts->cid = dtm_get_cid(); DtmTransactionListAppend(ts); + ts->nSubxids = xactGetCommittedChildren(&subxids); + DtmAddSubtransactions(ts, subxids, ts->nSubxids); } x->cid = ts->cid; - ts->status = TRANSACTION_STATUS_COMMITTED; DTM_TRACE((stderr, "Local transaction %u is committed at %lu\n", x->xid, x->cid)); } SpinLockRelease(&local->lock); } -void DtmLocalAbortPrepared(DtmTransState* x, GlobalTransactionId gtid) +void DtmLocalAbortPrepared(DtmCurrentTrans* x, GlobalTransactionId gtid) { Assert (gtid != NULL); @@ -726,13 +748,14 @@ void DtmLocalAbortPrepared(DtmTransState* x, GlobalTransactionId gtid) x->is_global = true; x->is_prepared = true; x->xid = id->xid; + free(id->subxids); DTM_TRACE((stderr, "Global transaction %u(%s) is preaborted\n", x->xid, gtid)); } SpinLockRelease(&local->lock); } -void DtmLocalAbort(DtmTransState* x) +void DtmLocalAbort(DtmCurrentTrans* x) { SpinLockAcquire(&local->lock); { @@ -741,9 +764,10 @@ void DtmLocalAbort(DtmTransState* x) if (x->is_prepared) { Assert(found); Assert(x->is_global); - } else if (!found) { - //Assert(!found); + } else { + Assert(!found); ts->cid = dtm_get_cid(); + ts->nSubxids = 0; DtmTransactionListAppend(ts); } x->cid = ts->cid; @@ -753,7 +777,7 @@ void DtmLocalAbort(DtmTransState* x) SpinLockRelease(&local->lock); } -void DtmLocalEnd(DtmTransState* x) +void DtmLocalEnd(DtmCurrentTrans* x) { x->is_global = false; x->is_prepared = false; @@ -761,31 +785,6 @@ void DtmLocalEnd(DtmTransState* x) x->cid = INVALID_CID; } -void DtmSetTransactionStatus(TransactionId xid, int nsubxids, TransactionId *subxids, XidStatus status, XLogRecPtr lsn) -{ - if (nsubxids != 0) { - SpinLockAcquire(&local->lock); - { - int i; - bool found; - DtmTransStatus* ts = (DtmTransStatus*)hash_search(xid2status, &xid, HASH_ENTER, &found); - if (!found) { - ts->cid = dtm_get_cid(); - } - ts->status = status; - for (i = 0; i < nsubxids; i++) { - DtmTransStatus* sts = (DtmTransStatus*)hash_search(xid2status, &subxids[i], HASH_ENTER, &found); - Assert(!found); - sts->status = status; - sts->cid = ts->cid; - DtmTransactionListInsertAfter(ts, sts); - } - } - SpinLockRelease(&local->lock); - } - PgTransactionIdSetTreeStatus(xid, nsubxids, subxids, status, lsn); -} - bool DtmDetectGlobalDeadLock(PGPROC* proc) { elog(WARNING, "Global deadlock?"); @@ -806,3 +805,36 @@ static cid_t DtmGetCsn(TransactionId xid) return csn; } +void DtmLocalSavePreparedState(GlobalTransactionId gtid) +{ + if (gtid != NULL) { + SpinLockAcquire(&local->lock); + { + DtmTransId* id = (DtmTransId*)hash_search(gtid2xid, gtid, HASH_FIND, NULL); + if (id != NULL) { + TransactionId* subxids; + int nSubxids = xactGetCommittedChildren(&subxids); + if (nSubxids != 0) { + id->subxids = (TransactionId*)malloc(nSubxids*sizeof(TransactionId)); + id->nSubxids = nSubxids; + memcpy(id->subxids, subxids, nSubxids*sizeof(TransactionId)); + } + } + } + SpinLockRelease(&local->lock); + } +} + +static void DtmAddSubtransactions(DtmTransStatus* ts, TransactionId* subxids, int nSubxids) +{ + int i; + for (i = 0; i < nSubxids; i++) { + bool found; + DtmTransStatus* sts = (DtmTransStatus*)hash_search(xid2status, &subxids[i], HASH_ENTER, &found); + Assert(!found); + sts->status = ts->status; + sts->cid = ts->cid; + sts->nSubxids = 0; + DtmTransactionListInsertAfter(ts, sts); + } +} diff --git a/pg_dtm.h b/pg_dtm.h index eedd3b2..f84892b 100644 --- a/pg_dtm.h +++ b/pg_dtm.h @@ -10,18 +10,18 @@ typedef struct { bool is_prepared; cid_t cid; cid_t snapshot; -} DtmTransState; +} DtmCurrentTrans; typedef char const* GlobalTransactionId; /* Initialize DTM extension */ void DtmInitialize(void); /* Invoked at start of any local or global transaction */ -void DtmLocalBegin(DtmTransState* x); +void DtmLocalBegin(DtmCurrentTrans* x); /* Extend local transaction to global by assigning upper bound CSN which is returned to coordinator */ -cid_t DtmLocalExtend(DtmTransState* x, GlobalTransactionId gtid); +cid_t DtmLocalExtend(DtmCurrentTrans* x, GlobalTransactionId gtid); /* Function called at first access to any datanode except first one involved in distributed transaction */ -cid_t DtmLocalAccess(DtmTransState* x, GlobalTransactionId gtid, cid_t snapshot); +cid_t DtmLocalAccess(DtmCurrentTrans* x, GlobalTransactionId gtid, cid_t snapshot); /* Mark transaction as in-doubt */ void DtmLocalBeginPrepare(GlobalTransactionId gtid); /* Choose CSN for global transaction */ @@ -29,14 +29,16 @@ cid_t DtmLocalPrepare(GlobalTransactionId gtid, cid_t cid); /* Assign CSN to global transaction */ void DtmLocalEndPrepare(GlobalTransactionId gtid, cid_t cid); /* Do local commit of global transaction */ -void DtmLocalCommitPrepared(DtmTransState* x, GlobalTransactionId gtid); +void DtmLocalCommitPrepared(DtmCurrentTrans* x, GlobalTransactionId gtid); /* Do local abort of global transaction */ -void DtmLocalAbortPrepared(DtmTransState* x, GlobalTransactionId gtid); +void DtmLocalAbortPrepared(DtmCurrentTrans* x, GlobalTransactionId gtid); /* Do local commit of global transaction */ -void DtmLocalCommit(DtmTransState* x); +void DtmLocalCommit(DtmCurrentTrans* x); /* Do local abort of global transaction */ -void DtmLocalAbort(DtmTransState* x); +void DtmLocalAbort(DtmCurrentTrans* x); /* Invoked at the end of any local or global transaction: free transaction state */ -void DtmLocalEnd(DtmTransState* x); +void DtmLocalEnd(DtmCurrentTrans* x); +/* Save global preapred transactoin state */ +void DtmLocalSavePreparedState(GlobalTransactionId gtid); #endif From 877f5cb03fb97ed922aaaddcd4f681374dac2b16 Mon Sep 17 00:00:00 2001 From: Konstantin Knizhnik Date: Thu, 3 Dec 2015 12:35:12 +0300 Subject: [PATCH 45/46] Add dtm_recovery --- dtm_recovery/dtm_recovery.cpp | 129 ++++++++++++++++++++++++++++++++++ dtm_recovery/makefile | 10 +++ pg_dtm.c | 26 +++++++ tests/dtmbench.cpp | 12 ++-- 4 files changed, 171 insertions(+), 6 deletions(-) create mode 100644 dtm_recovery/dtm_recovery.cpp create mode 100644 dtm_recovery/makefile diff --git a/dtm_recovery/dtm_recovery.cpp b/dtm_recovery/dtm_recovery.cpp new file mode 100644 index 0000000..338dfdd --- /dev/null +++ b/dtm_recovery/dtm_recovery.cpp @@ -0,0 +1,129 @@ +#include +#include +#include +#include + +#include +#include +#include + +using namespace std; +using namespace pqxx; + +int main (int argc, char* argv[]) +{ + if (argc == 1){ + printf("Use -h to show usage options\n"); + return 1; + } + vector connections; + set prepared_xacts; + set committed_xacts; + bool verbose = false; + for (int i = 1; i < argc; i++) { + if (argv[i][0] == '-') { + switch (argv[i][1]) { + case 'C': + case 'c': + connections.push_back(string(argv[++i])); + continue; + case 'v': + verbose = true; + continue; + } + } + printf("Perform recovery of pg_tsdtm cluster.\n" + "Usage: dtm_recovery {options}\n" + "Options:\n" + "\t-c STR\tdatabase connection string\n" + "\t-v\tverbose mode: print extra information while processing\n"); + return 1; + } + if (verbose) { + cout << "Collecting information about prepared transactions...\n"; + } + for (vector::iterator ic = connections.begin(); ic != connections.end(); ++ic) + { + if (verbose) { + cout << "Connecting to " << *ic << "...\n"; + } + connection con(*ic); + work txn(con); + result r = txn.exec("select gid from pg_prepared_xacts"); + for (result::const_iterator it = r.begin(); it != r.end(); ++it) + { + string gid = it.at("gid").as(string()); + prepared_xacts.insert(gid); + } + txn.commit(); + } + if (verbose) { + cout << "Prepared transactions: "; + for (set::iterator it = prepared_xacts.begin(); it != prepared_xacts.end(); ++it) + { + cout << *it << ", "; + } + cout << "\nChecking which of them are committed...\n"; + } + for (vector::iterator ic = connections.begin(); ic != connections.end(); ++ic) + { + if (verbose) { + cout << "Connecting to " << *ic << "...\n"; + } + connection con(*ic); + work txn(con); + con.prepare("commit-check", "select * from pg_committed_xacts where gid=$1"); + for (set::iterator it = prepared_xacts.begin(); it != prepared_xacts.end(); ++it) + { + string gid = *it; + result r = txn.prepared("commit-check")(gid).exec(); + if (!r.empty()) { + committed_xacts.insert(gid); + } + } + txn.commit(); + } + if (verbose) { + cout << "Committed transactions: "; + for (set::iterator it = committed_xacts.begin(); it != committed_xacts.end(); ++it) + { + cout << *it << ", "; + } + cout << "\nCommitting them at all nodes...\n"; + } + for (vector::iterator ic = connections.begin(); ic != connections.end(); ++ic) + { + if (verbose) { + cout << "Connecting to " << *ic << "...\n"; + } + connection con(*ic); + work txn(con); + con.prepare("commit-check", "select * from pg_committed_xacts where gid=$1"); + con.prepare("commit-prepared", "commit prepared $1"); + con.prepare("rollback-prepared", "rollback prepared $1"); + result r = txn.exec("select gid from pg_prepared_xacts"); + for (result::const_iterator it = r.begin(); it != r.end(); ++it) + { + string gid = it.at("gid").as(string()); + result rc = txn.prepared("commit-check")(gid).exec(); + if (rc.empty()) { + if (committed_xacts.find(gid) != committed_xacts.end()) { + if (verbose) { + cout << "Commit transaction " << gid << "\n"; + } + txn.prepared("commit-prepared")(gid); + } else { + if (verbose) { + cout << "Rollback transaction " << gid << "\n"; + } + txn.prepared("rollback-prepared")(gid); + } + } + } + txn.commit(); + } + if (verbose) { + cout << "Recovery completed\n"; + } + return 0; +} diff --git a/dtm_recovery/makefile b/dtm_recovery/makefile new file mode 100644 index 0000000..27bdf3f --- /dev/null +++ b/dtm_recovery/makefile @@ -0,0 +1,10 @@ +CXX=g++ +CXXFLAGS=-g -Wall -O0 -pthread + +all: dtm_recovery + +dtm_recovery: dtm_recovery.cpp + $(CXX) $(CXXFLAGS) -o dtm_recovery dtm_recovery.cpp -lpqxx + +clean: + rm -f dtm_recovery diff --git a/pg_dtm.c b/pg_dtm.c index 8441a49..6afb19b 100644 --- a/pg_dtm.c +++ b/pg_dtm.c @@ -25,6 +25,7 @@ #include "access/xlog.h" #include "access/clog.h" #include "access/twophase.h" +#include "executor/spi.h" #include "utils/hsearch.h" #include "utils/tqual.h" #include @@ -81,6 +82,7 @@ static DtmNodeState* local; static DtmCurrentTrans dtm_tx; static uint64 totalSleepInterrupts; static int DtmVacuumDelay; +static bool DtmRecordCommits; static Snapshot DtmGetSnapshot(Snapshot snapshot); static TransactionId DtmGetOldestXmin(Relation rel, bool ignoreVacuum); @@ -211,6 +213,19 @@ _PG_init(void) NULL ); + DefineCustomBoolVariable( + "dtm.record_commits", + "Store information about committed global transactions in pg_committed_xacts table", + NULL, + &DtmRecordCommit, + false, + PGC_BACKEND, + 0, + NULL, + NULL, + NULL + ); + /* * Install hooks. @@ -684,6 +699,17 @@ void DtmLocalEndPrepare(GlobalTransactionId gtid, cid_t cid) DTM_TRACE((stderr, "Prepare transaction %u(%s) with CSN %lu\n", id->xid, gtid, cid)); } SpinLockRelease(&local->lock); + if (DtmRecordCommits) { + char stmt[MAX_GTID_SIZE + 64]; + int rc; + sprintf(stmt, "insert into pg_committed_xacts values ('%s')", gtid); + SPI_connect(); + rc = SPI_execute(stmt, true, 0); + SPI_finish(); + if (rc != SPI_OK_INSERT) { + elog(ERROR, "Failed to insert GTID %s in table pg_committed_xacts", gtid); + } + } } void DtmLocalCommitPrepared(DtmCurrentTrans* x, GlobalTransactionId gtid) diff --git a/tests/dtmbench.cpp b/tests/dtmbench.cpp index c4570d2..37aee0e 100644 --- a/tests/dtmbench.cpp +++ b/tests/dtmbench.cpp @@ -17,17 +17,17 @@ using namespace std; using namespace pqxx; template -class unique_ptr +class my_unique_ptr { T* ptr; public: - unique_ptr(T* p = NULL) : ptr(p) {} - ~unique_ptr() { delete ptr; } + my_unique_ptr(T* p = NULL) : ptr(p) {} + ~my_unique_ptr() { delete ptr; } T& operator*() { return *ptr; } T* operator->() { return ptr; } void operator=(T* p) { ptr = p; } - void operator=(unique_ptr& other) { + void operator=(my_unique_ptr& other) { ptr = other.ptr; other.ptr = NULL; } @@ -122,7 +122,7 @@ int64_t execQuery( transaction_base& txn, char const* sql, ...) void* reader(void* arg) { thread& t = *(thread*)arg; - vector< unique_ptr > conns(cfg.connections.size()); + vector< my_unique_ptr > conns(cfg.connections.size()); for (size_t i = 0; i < conns.size(); i++) { conns[i] = new connection(cfg.connections[i]); } @@ -130,7 +130,7 @@ void* reader(void* arg) while (running) { csn_t snapshot = 0; - vector< unique_ptr > txns(conns.size()); + vector< my_unique_ptr > txns(conns.size()); time_t start = getCurrentTime(); for (size_t i = 0; i < conns.size(); i++) { txns[i] = new work(*conns[i]); From 5ac02f84890926631d2aab4a41c2ef350c1ac167 Mon Sep 17 00:00:00 2001 From: Stas Kelvich Date: Wed, 9 Dec 2015 19:29:47 +0300 Subject: [PATCH 46/46] typo --- pg_dtm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pg_dtm.c b/pg_dtm.c index 6afb19b..0dc53f0 100644 --- a/pg_dtm.c +++ b/pg_dtm.c @@ -217,7 +217,7 @@ _PG_init(void) "dtm.record_commits", "Store information about committed global transactions in pg_committed_xacts table", NULL, - &DtmRecordCommit, + &DtmRecordCommits, false, PGC_BACKEND, 0, pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy